text:
/*===-- wtk/wgl.c -------------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#include "wtk/wgl.h"

#if WTK_PLATFORM == WTK_PLATFORM_WINDOWS

#include <windows.h>

WTK_BEGIN_EXTERN_C

/* HACK(mtwilliams): We pun undecorated names with the preprocessor because
 * Windows headers declare functions of the same name.
 */

static HMODULE gl;
static HMODULE gdi;

#define WGL_DRAW_TO_WINDOW_ARB                    0x2001
#define WGL_DRAW_TO_BITMAP_ARB                    0x2002

#define WGL_ACCELERATION_ARB                      0x2003
#define WGL_SUPPORT_OPENGL_ARB                    0x2010
#define WGL_SUPPORT_GDI_ARB                       0x200F

#define WGL_PIXEL_TYPE_ARB                        0x2013
#define WGL_TYPE_RGBA_ARB                         0x202B

#define WGL_COLOR_BITS_ARB                        0x2014
#define WGL_RED_BITS_ARB                          0x2015
#define WGL_GREEN_BITS_ARB                        0x2017
#define WGL_BLUE_BITS_ARB                         0x2019
#define WGL_ALPHA_BITS_ARB                        0x201B
#define WGL_DEPTH_BITS_ARB                        0x2022
#define WGL_STENCIL_BITS_ARB                      0x2023

#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB          0x20A9

#define WGL_COLORSPACE_EXT                        0x309D
#define WGL_COLORSPACE_SRGB_EXT                   0x3089
#define WGL_COLORSPACE_LINEAR_EXT                 0x308A

#define WGL_SWAP_METHOD_ARB                       0x2007
#define WGL_DOUBLE_BUFFER_ARB                     0x2011

#define WGL_STEREO_ARB                            0x2012

#define WGL_SWAP_EXCHANGE_ARB                     0x2028
#define WGL_SWAP_COPY_ARB                         0x2029
#define WGL_SWAP_UNDEFINED_ARB                    0x202A

#define WGL_NO_ACCELERATION_ARB                   0x2025
#define WGL_GENERIC_ACCELERATION_ARB              0x2026
#define WGL_FULL_ACCELERATION_ARB                 0x2027

#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092
#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126
#define WGL_CONTEXT_LAYER_PLANE_ARB               0x2093
#define WGL_CONTEXT_FLAGS_ARB                     0x2094
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB          0x2097

#define WGL_CONTEXT_DEBUG_BIT_ARB                 0x0001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB    0x0002

#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB          0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002

#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB     0x0000
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB    0x2098

typedef const char *(WINAPI *WGLGETEXTENSIONSSTRINGPROC)(HDC hdc);
typedef void *(WINAPI *WGLGETPROCADDRESSPROC)(const char *name);

#define wglGetExtensionsString __wtk_wglGetExtensionsString
#define wglGetProcAddress __wtk_wglGetProcAddress

static WGLGETEXTENSIONSSTRINGPROC __wtk_wglGetExtensionsString = NULL;
static WGLGETPROCADDRESSPROC __wtk_wglGetProcAddress = NULL;

typedef HGLRC (WINAPI *WGLCREATECONTEXTPROC)(HDC hdc);
typedef BOOL (WINAPI *WGLDELETECONTEXTPROC)(HGLRC hglrc);
typedef BOOL (WINAPI *WGLMAKECURRENTPROC)(HDC hdc, HGLRC hglrc);

#define wglCreateContext __wtk_wglCreateContext
#define wglDeleteContext __wtk_wglDeleteContext
#define wglMakeCurrent __wtk_wglMakeCurrent

static WGLCREATECONTEXTPROC __wtk_wglCreateContext = NULL;
static WGLDELETECONTEXTPROC __wtk_wglDeleteContext = NULL;
static WGLMAKECURRENTPROC __wtk_wglMakeCurrent = NULL;

typedef BOOL (WINAPI *WGLCHOOSEPIXELFORMATPROC)(HDC hdc, const UINT *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
typedef HGLRC (WINAPI *WGLCREATECONTEXTATTRIBSPROC)(HDC hDC, HGLRC hShareContext, const UINT *attribList);

#define wglChoosePixelFormat __wtk_wglChoosePixelFormat
#define wglCreateContextAttribs __wtk_wglCreateContextAttribs

static WGLCHOOSEPIXELFORMATPROC __wtk_wglChoosePixelFormat = NULL;
static WGLCREATECONTEXTATTRIBSPROC __wtk_wglCreateContextAttribs = NULL;

typedef BOOL (WINAPI *WGLSWAPINTERVALPROC)(int interval);
typedef BOOL (WINAPI *SWAPBUFFERSPROC)(HDC hdc);

#define wglSwapInterval __wtk_wglSwapInterval
#define SwapBuffers __wtk_SwapBuffers

static WGLSWAPINTERVALPROC __wtk_wglSwapInterval = NULL;
static SWAPBUFFERSPROC __wtk_SwapBuffers = NULL;

static const char *WGL_ACTUAL_CONTEXT_CLASS    = "27fd51f3-b7f6-4ccf-87b0-94458ea50410";
static const char *WGL_BOOTSTRAP_CONTEXT_CLASS = "a5b92a99-4f06-41c2-a0db-a46f908eaed1";

static void wtk_wgl_register_context_classes(void)
{
  /* We register two distinct window classes to aid differentiation of context
   * types. One is for our bootstrap context and the other for the contexts we
   * use.
   */

  WNDCLASSEXA actual_context_class;
  WNDCLASSEXA bootstrap_context_class;

  memset((void *)&actual_context_class, 0, sizeof(WNDCLASSEXA));
  memset((void *)&bootstrap_context_class, 0, sizeof(WNDCLASSEXA));

  actual_context_class.cbSize        = sizeof(WNDCLASSEXA);
  actual_context_class.style         = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
  actual_context_class.lpfnWndProc   = DefWindowProc;
  actual_context_class.hInstance     = GetModuleHandle(NULL);
  actual_context_class.hCursor       = LoadCursor(NULL, IDC_ARROW);
  actual_context_class.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  actual_context_class.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
  actual_context_class.lpszClassName = WGL_ACTUAL_CONTEXT_CLASS;

  static const BOOL registered_actual_context_class_succesfully =
    RegisterClassExA(&actual_context_class);

  wtk_assert_release(registered_actual_context_class_succesfully);

  bootstrap_context_class.cbSize        = sizeof(WNDCLASSEXA);
  bootstrap_context_class.style         = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
  bootstrap_context_class.lpfnWndProc   = DefWindowProc;
  bootstrap_context_class.hInstance     = GetModuleHandle(NULL);
  bootstrap_context_class.hCursor       = LoadCursor(NULL, IDC_ARROW);
  bootstrap_context_class.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  bootstrap_context_class.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
  bootstrap_context_class.lpszClassName = WGL_BOOTSTRAP_CONTEXT_CLASS;

  static const BOOL registered_boostrap_context_class_succesfully =
    RegisterClassExA(&bootstrap_context_class);

  wtk_assert_release(registered_boostrap_context_class_succesfully);
}

static void wtk_wgl_check_for_required_extensions(HWND hwnd, HDC hdc, HGLRC hglrc)
{
  (void)hwnd;
  (void)hglrc;

  const char *extensions = wglGetExtensionsString(hdc);
  wtk_assert_release(extensions != NULL);

  /* TODO(mtwilliams): Should we require WGL_ARB_context_flush_control? */
  static const char *required[] = {
    "WGL_ARB_pixel_format",
    "WGL_ARB_create_context",
    "WGL_ARB_create_context_profile",
    "WGL_EXT_swap_control"
  };

  static const unsigned count = sizeof(required) / sizeof(required[0]);

  for (unsigned i = 0; i < count; ++i) {
    /* TODO(mtwilliams): Replace `strstr` with a custom implementation to
     * remove dependence on standard library?
     */
    const unsigned advertised = (strstr(extensions, required[i]) != 0);

  #if 1
    wtk_assert_release(advertised);
  #else
    wtk_assertf_release(advertised, "Required extension `%s` is not available!", required[i]);
  #endif
  }
}

static void wtk_wgl_create_bootstrap_context_window(HWND *bootstrap_context_window)
{
  *bootstrap_context_window =
    CreateWindowA(WGL_BOOTSTRAP_CONTEXT_CLASS,
                  WGL_BOOTSTRAP_CONTEXT_CLASS,
                  WS_POPUP | WS_DISABLED,
                  0, 0, 1, 1,
                  NULL,
                  NULL,
                  GetModuleHandle(NULL),
                  NULL);

  wtk_assert_release(*bootstrap_context_window != NULL);
}

static void wtk_wgl_create_bootstrap_context(HWND bootstrap_context_window,
                                             HDC *bootstrap_context_hdc,
                                             HGLRC *bootstrap_context_hglrc)
{
  *bootstrap_context_hdc = GetDC(bootstrap_context_window);
  wtk_assert_release(*bootstrap_context_hdc != NULL);

  PIXELFORMATDESCRIPTOR pixel_format_desc;
  memset((void *)&pixel_format_desc, 0, sizeof(PIXELFORMATDESCRIPTOR));

  pixel_format_desc.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
  pixel_format_desc.nVersion     = 1;
  pixel_format_desc.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  pixel_format_desc.iPixelType   = PFD_TYPE_RGBA;
  pixel_format_desc.cColorBits   = 24;
  pixel_format_desc.cAlphaBits   = 0;
  pixel_format_desc.cDepthBits   = 0;
  pixel_format_desc.cStencilBits = 0;
  pixel_format_desc.iLayerType   = PFD_MAIN_PLANE;

  const int pixel_format = ChoosePixelFormat(*bootstrap_context_hdc,
                                             &pixel_format_desc);
  wtk_assert_release(pixel_format != 0);

  const BOOL set_pixel_format_succesfully = !!SetPixelFormat(*bootstrap_context_hdc,
                                                             pixel_format,
                                                             &pixel_format_desc);
  wtk_assert_release(set_pixel_format_succesfully);

  *bootstrap_context_hglrc = wglCreateContext(*bootstrap_context_hdc);
  wtk_assert_release(*bootstrap_context_hglrc != NULL);
}

void wtk_wgl_init(void)
{
  gl = LoadLibraryA("opengl32.dll");
  wtk_assert_release(gl != NULL);

  wglGetProcAddress = (WGLGETPROCADDRESSPROC)GetProcAddress(gl, "wglGetProcAddress");
  wglCreateContext  = (WGLCREATECONTEXTPROC)GetProcAddress(gl, "wglCreateContext");
  wglDeleteContext  = (WGLDELETECONTEXTPROC)GetProcAddress(gl, "wglDeleteContext");
  wglMakeCurrent    = (WGLMAKECURRENTPROC)GetProcAddress(gl, "wglMakeCurrent");

  wtk_wgl_register_context_classes();

  HWND bootstrap_context_window;
  HDC bootstrap_context_hdc;
  HGLRC bootstrap_context_hglrc;

  wtk_wgl_create_bootstrap_context_window(&bootstrap_context_window);

  wtk_wgl_create_bootstrap_context(bootstrap_context_window,
                                   &bootstrap_context_hdc,
                                   &bootstrap_context_hglrc);

  wglMakeCurrent(bootstrap_context_hdc, bootstrap_context_hglrc);

  /* NOTE(mtwilliams): We assume that `WGL_ARB_extensions_string` is available. */
  wglGetExtensionsString = (WGLGETEXTENSIONSSTRINGPROC)wglGetProcAddress("wglGetExtensionsStringARB");

  wtk_wgl_check_for_required_extensions(bootstrap_context_window,
                                        bootstrap_context_hdc,
                                        bootstrap_context_hglrc);

  wglCreateContext        = (WGLCREATECONTEXTPROC)wtk_wgl_get_proc_address("wglCreateContext");
  wglDeleteContext        = (WGLDELETECONTEXTPROC)wtk_wgl_get_proc_address("wglDeleteContext");
  wglMakeCurrent          = (WGLMAKECURRENTPROC)wtk_wgl_get_proc_address("wglMakeCurrent");
  wglChoosePixelFormat    = (WGLCHOOSEPIXELFORMATPROC)wtk_wgl_get_proc_address("wglChoosePixelFormatARB");
  wglCreateContextAttribs = (WGLCREATECONTEXTATTRIBSPROC)wtk_wgl_get_proc_address("wglCreateContextAttribsARB");
  wglSwapInterval         = (WGLSWAPINTERVALPROC)wtk_wgl_get_proc_address("wglSwapIntervalEXT");

  wglMakeCurrent(NULL, NULL);

  /* TODO(mtwilliams): Determine if we should keep the bootstrap context around
   * until shutdown. Probably not.
   */
  wglDeleteContext(bootstrap_context_hglrc);
  ReleaseDC(bootstrap_context_window, bootstrap_context_hdc);
  DestroyWindow(bootstrap_context_window);

  gdi = LoadLibraryA("gdi32.dll");
  wtk_assert_release(gdi != NULL);

  SwapBuffers = (SWAPBUFFERSPROC)GetProcAddress(gdi, "SwapBuffers");
}

void wtk_wgl_shutdown(void)
{
  wglGetExtensionsString  = NULL;
  wglGetProcAddress       = NULL;
  wglCreateContext        = NULL;
  wglDeleteContext        = NULL;
  wglMakeCurrent          = NULL;
  wglChoosePixelFormat    = NULL;
  wglCreateContextAttribs = NULL;
  wglSwapInterval         = NULL;

  SwapBuffers             = NULL;

  FreeLibrary(gl);
  FreeLibrary(gdi);

  gl = NULL;
  gdi = NULL;
}

void *wtk_wgl_get_proc_address(const char *name)
{
  wtk_assert_debug(name != NULL);

  if (void *addr = wglGetProcAddress(name))
    return addr;

  return GetProcAddress(gl, name);
}

struct wtk_wgl_context {
  HWND window;

  /* Indicates if we own `window` and should destroy it. */
  unsigned owner_of_window;

  /* Drawing and resource contexts. */
  HDC hdc;
  HGLRC hglrc;

  /* Cached for surfaces. */
  int pixel_format;
  PIXELFORMATDESCRIPTOR pixel_format_desc;
};

static void wtk_wgl_create_context_window(HWND *actual_context_window)
{
  *actual_context_window =
    CreateWindowA(WGL_ACTUAL_CONTEXT_CLASS,
                  WGL_ACTUAL_CONTEXT_CLASS,
                  WS_POPUP | WS_DISABLED,
                  0, 0, 1, 1,
                  NULL,
                  NULL,
                  GetModuleHandle(NULL),
                  NULL);

  wtk_assert_release(*actual_context_window != NULL);
}

wtk_wgl_context_t *wtk_wgl_create_context(const wtk_wgl_context_creation_params_t *ccp)
{
  wtk_assert_debug(ccp != NULL);

  wtk_wgl_context_t *context =
    (wtk_wgl_context_t *)wtk_allocate_s(sizeof(wtk_wgl_context_t), 16);

  wtk_wgl_create_context_window(&context->window);

  context->hdc = GetDC(context->window);
  wtk_assert_release(context->hdc != NULL);

  context->owner_of_window = 1;

  const UINT pixel_format_attributes[] = {
    /* Goes without saying... */
    WGL_DRAW_TO_WINDOW_ARB, TRUE,
    WGL_SUPPORT_OPENGL_ARB, TRUE,
    WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,

    WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
    WGL_COLOR_BITS_ARB, 24,
    WGL_RED_BITS_ARB, 8,
    WGL_GREEN_BITS_ARB, 8,
    WGL_BLUE_BITS_ARB, 8,
    WGL_ALPHA_BITS_ARB, 0,

    /* PERF(mtwilliams): Determine if `WGL_SWAP_EXCHANGE_ARB` is fast path, as
     * some say it is. It should be as it's just exchanging pointers rather
     * than copying contents like `WGL_SWAP_COPY_ARB`. Except,
     * `WGL_SWAP_COPY_ARB` is analogous to `DXGI_SWAP_EFFECT_DISCARD` which is
     * the fast path for D3D11...
     */
    WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB,
    WGL_DOUBLE_BUFFER_ARB, TRUE,

    0
  };

  /* TODO(mtwilliams): Determine if we can pass `NULL`. */
  UINT unused;

  const BOOL chose_pixel_format_succesfully =
    wglChoosePixelFormat(context->hdc,
                         &pixel_format_attributes[0], NULL, 1,
                         &context->pixel_format,
                         &unused);

  wtk_assert_release(chose_pixel_format_succesfully);

  /* As GDI expects the older style descriptor, we grab that. */
  DescribePixelFormat(context->hdc,
                      context->pixel_format,
                      sizeof(PIXELFORMATDESCRIPTOR),
                      &context->pixel_format_desc);

  /* Set traditionally. Windows will use the identifier to dig up the extended
   * attributes requested by `wglChoosePixelFormatARB`.
   */
  SetPixelFormat(context->hdc,
                 context->pixel_format,
                 &context->pixel_format_desc);

  UINT flags = 0x00000000;

  if (ccp->flags & WTK_WGL_CONTEXT_DEBUG)
    flags |= WGL_CONTEXT_DEBUG_BIT_ARB;

  UINT profile;

  if (ccp->version.major >= 3)
    profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
  else
    profile = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;

  const UINT context_attributes[] = {
    WGL_CONTEXT_MAJOR_VERSION_ARB, ccp->version.major,
    WGL_CONTEXT_MINOR_VERSION_ARB, ccp->version.minor,

    WGL_CONTEXT_PROFILE_MASK_ARB, profile,

    /* We don't seem to incur a context release and corresponding flush when
     * only rebinding `hdc` and not `hglrc`. Still, relying on the implicit
     * synchronization of `SwapBuffers` offers greater potential for
     * performance.
     */
    WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB,

    WGL_CONTEXT_FLAGS_ARB, flags,

    0
  };

  context->hglrc = wglCreateContextAttribs(context->hdc,
                                           ccp->share ?
                                             ccp->share->hglrc : NULL,
                                           &context_attributes[0]);

#if 1
  wtk_assert_release(context->hglrc != NULL);
#else
  wtk_assertf_release(context->hglrc, "Unable to create context!");
#endif

  return context;
}

void wtk_wgl_destroy_context(wtk_wgl_context_t *context)
{
  wtk_assert_debug(context != NULL);

  wglDeleteContext(context->hglrc);
  ReleaseDC(context->window, context->hdc);

  if (context->owner_of_window)
    DestroyWindow(context->window);

  wtk_free((void *)context);
}

struct wtk_wgl_surface {
  HWND window;
  HDC hdc;
};

wtk_wgl_surface_t *wtk_wgl_create_surface(wtk_wgl_context_t *context,
                                          HWND window)
{
  wtk_assert_debug(IsWindow(window));

  wtk_wgl_surface_t *surface =
    (wtk_wgl_surface_t *)wtk_allocate_s(sizeof(wtk_wgl_surface_t), 16);

  surface->window = (HWND)window;
  surface->hdc = GetDC(surface->window);

  SetPixelFormat(surface->hdc,
                 context->pixel_format,
                 &context->pixel_format_desc);

  return surface;
}

void wtk_wgl_destroy_surface(wtk_wgl_surface_t *surface)
{
  wtk_assert_debug(surface != NULL);

  /* TODO(mtwilliams): Make sure `surface->hdc` is not current. */
  ReleaseDC(surface->window, surface->hdc);

  wtk_free((void *)surface);
}

void wtk_wgl_dimensions_of_surface(wtk_wgl_surface_t *surface,
                                   wtk_uint32_t *width,
                                   wtk_uint32_t *height)
{
  wtk_assert_debug(surface != NULL);
  wtk_assert_debug(width != NULL);
  wtk_assert_debug(height != NULL);

  RECT area = { 0, };
  GetClientRect(surface->window, &area);

  *width = area.right - area.left;
  *height = area.bottom - area.top;
}

void wtk_wgl_bind(wtk_wgl_context_t *context,
                  wtk_wgl_surface_t *surface)
{
  if (context) {
    wglMakeCurrent(surface ? surface->hdc : context->hdc, context->hglrc);
  } else {
    wglMakeCurrent(NULL, NULL);
  }
}

void wtk_wgl_present(wtk_wgl_surface_t *surface,
                     wtk_uint32_t flags)
{
  wtk_assert_debug(surface != NULL);

  if (flags & WTK_WGL_PRESENT_SYNCHRONIZE)
    wglSwapInterval(1);
  else
    wglSwapInterval(0);

  SwapBuffers(surface->hdc);
}

WTK_END_EXTERN_C

#endif


text:
/*===-- wtk/render.c ----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#include "wtk/render.h"

/* For batches. */
#include "wtk/draw.h"

#include "wtk/gl.h"

WTK_BEGIN_EXTERN_C

typedef struct wtk_renderer {
  /*! Monotonically increasing count of frames rendered. */
  wtk_uint32_t frames;

  /* Simple shader for rendering a bunch of `wtk_vertex_t`. */
  wtk_uint32_t program;

  wtk_uint32_t batch_uniform_loc;
  wtk_uint32_t dimensions_uniform_loc;
  wtk_uint32_t debug_uniform_loc;

  /*! Allocations for lifetime of renderer. */
  wtk_block_t permanent;

  /*! Allocations for lifetime of a frame. */
  wtk_block_t transient;
} wtk_renderer_t;

static wtk_renderer_t *r = NULL;

/* Evenly distributed colors. Useful for debug visualization. */
static const wtk_uint32_t COLORS[32] = {
  0x7f7e3fff, 0x3faf7fff, 0x7f3f1dff, 0x097f3fff, 0x483f7fff, 0x7f5b3fff,
  0x3f7fedff, 0x7f3f40ff, 0x2b7f3fff, 0x3f9a7fff, 0x7f3f08ff, 0x3f7fcbff,
  0x5d3f7fff, 0x7f713fff, 0x3fbd7fff, 0x7f3f2bff, 0x167f3fff, 0x3f857fff,
  0x7f4e3fff, 0x3f7fe0ff, 0x723f7fff, 0x387f3fff, 0x3fa77fff, 0x7f3f15ff,
  0x017f3fff, 0x503f7fff, 0x7f633fff, 0x3f7ff5ff, 0x7f3f38ff, 0x237f3fff,
  0x3f927fff, 0x7f413fff
};

static const char *VERTEX_SHADER_SOURCE =
  "#version 140                                                           \n" \
  "                                                                       \n" \
  "#extension GL_ARB_explicit_attrib_location : enable                    \n" \
  "                                                                       \n" \
  "// Toggles visualization of primitives.                                \n" \
  "uniform bool debug;                                                    \n" \
  "                                                                       \n" \
  "// Globally unique identifier assigned to batch.                       \n" \
  "uniform uint batch;                                                    \n" \
  "                                                                       \n" \
  "// Canvas dimensions.                                                  \n" \
  "uniform uvec2 dimensions;                                              \n" \
  "                                                                       \n" \
  "// Input.                                                              \n" \
  "layout(location = 0) in vec2 vs_position;                              \n" \
  "layout(location = 1) in vec2 vs_uv;                                    \n" \
  "layout(location = 2) in vec4 vs_color;                                 \n" \
  "layout(location = 3) in uint vs_texture;                               \n" \
  "                                                                       \n" \
  "// Output.                                                             \n" \
  "out vec2 fs_uv;                                                        \n" \
  "out vec4 fs_color;                                                     \n" \
  "flat out uint fs_texture;                                              \n" \
  "                                                                       \n" \
  "const vec3 colors[32] = vec3[](                                        \n" \
  "  vec3(0.800f, 0.400f, 0.722f), vec3(0.192f, 0.800f, 0.400f),          \n" \
  "  vec3(0.400f, 0.282f, 0.800f), vec3(0.800f, 0.435f, 0.400f),          \n" \
  "  vec3(0.400f, 0.800f, 0.349f), vec3(0.263f, 0.400f, 0.800f),          \n" \
  "  vec3(0.800f, 0.788f, 0.400f), vec3(0.400f, 0.498f, 0.800f),          \n" \
  "  vec3(0.800f, 0.400f, 0.588f), vec3(0.059f, 0.800f, 0.400f),          \n" \
  "  vec3(0.047f, 0.400f, 0.800f), vec3(0.800f, 0.573f, 0.400f),          \n" \
  "  vec3(0.400f, 0.800f, 0.482f), vec3(0.800f, 0.400f, 0.804f),          \n" \
  "  vec3(0.275f, 0.800f, 0.400f), vec3(0.400f, 0.365f, 0.800f),          \n" \
  "  vec3(0.800f, 0.400f, 0.455f), vec3(0.400f, 0.800f, 0.267f),          \n" \
  "  vec3(0.180f, 0.400f, 0.800f), vec3(0.800f, 0.706f, 0.400f),          \n" \
  "  vec3(0.400f, 0.584f, 0.800f), vec3(0.800f, 0.400f, 0.671f),          \n" \
  "  vec3(0.141f, 0.800f, 0.400f), vec3(0.400f, 0.231f, 0.800f),          \n" \
  "  vec3(0.800f, 0.486f, 0.400f), vec3(0.400f, 0.800f, 0.400f),          \n" \
  "  vec3(0.314f, 0.400f, 0.800f), vec3(0.357f, 0.800f, 0.400f),          \n" \
  "  vec3(0.400f, 0.447f, 0.800f), vec3(0.800f, 0.400f, 0.537f),          \n" \
  "  vec3(0.008f, 0.800f, 0.400f), vec3(0.098f, 0.400f, 0.800f)           \n" \
  ");                                                                     \n" \
  "                                                                       \n" \
  "void main() {                                                          \n" \
  "  vec2 position = vs_position / vec2(dimensions);                      \n" \
  "                                                                       \n" \
  "  // Origin is upper left, but OpenGL uses lower left convention.      \n" \
  "  position.y = 1.0f - position.y;                                      \n" \
  "                                                                       \n" \
  "  // Map to normalized device coordinates.                             \n" \
  "  gl_Position = vec4(position * 2.0f - 1.0f, 0.5f, 1.0f);              \n" \
  "                                                                       \n" \
  "  if (debug) {                                                         \n" \
  "    // Assign a color per triangle.                                    \n" \
  "    fs_uv = vec2(0.0f, 0.0f);                                          \n" \
  "    fs_color = vec4(colors[(gl_VertexID / 3) % 32], 1.0f);             \n" \
  "    fs_texture = 0u;                                                   \n" \
  "  } else {                                                             \n" \
  "    fs_uv = vs_uv;                                                     \n" \
  "    fs_color = vs_color;                                               \n" \
  "    fs_texture = vs_texture;                                           \n" \
  "  }                                                                    \n" \
  "}";

static const char *FRAGMENT_SHADER_SOURCE =
  "#version 140                                                           \n" \
  "                                                                       \n" \
  "#extension GL_ARB_explicit_attrib_location : enable                    \n" \
  "                                                                       \n" \
  "// Toggles visualization of primitives.                                \n" \
  "uniform bool debug;                                                    \n" \
  "                                                                       \n" \
  "// Globally unique identifier assigned to batch.                       \n" \
  "uniform uint batch;                                                    \n" \
  "                                                                       \n" \
  "// Canvas dimensions.                                                  \n" \
  "uniform uvec2 dimensions;                                              \n" \
  "                                                                       \n" \
  "#if 0                                                                  \n" \
  "uniform sampler2D textures[8];                                         \n" \
  "#endif                                                                 \n" \
  "                                                                       \n" \
  "// Input.                                                              \n" \
  "in vec2 fs_uv;                                                         \n" \
  "in vec4 fs_color;                                                      \n" \
  "in uint fs_texture;                                                    \n" \
  "                                                                       \n" \
  "// Output.                                                             \n" \
  "layout(location = 0) out vec4 gl_FragColor;                            \n" \
  "                                                                       \n" \
  "void main() {                                                          \n" \
  "  vec4 base = vec4(1.0f, 1.0f, 1.0f, 1.0f);                            \n" \
  "                                                                       \n" \
  "#if 0                                                                  \n" \
  "  /* Non-uniform control flow. Can't rely on mipmaps? */               \n" \
  "  if (texture != 0)                                                    \n" \
  "    base = texture(textures[fs_texture],                               \n" \
  "                   vec2(fs_uv.x, 1.0f - fs_uv));                       \n" \
  "#endif                                                                 \n" \
  "                                                                       \n" \
  "  gl_FragColor = base * fs_color;                                      \n" \
  "};";

void wtk_renderer_init(void)
{
  r = (wtk_renderer_t *)wtk_allocate_s(sizeof(wtk_renderer_t), 16);

  r->frames = 0;

  r->permanent.base   = (wtk_uintptr_t)wtk_allocate_s(65535, 16);
  r->permanent.offset = 0;
  r->permanent.size   = 65535;

  r->transient.base   = (wtk_uintptr_t)wtk_allocate_s(65535, 16);
  r->transient.offset = 0;
  r->transient.size   = 65535;

  wtk_ogl_init();

  r->program = glCreateProgram(); {
    wtk_uint32_t vs = glCreateShader(GL_VERTEX_SHADER),
                 fs = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(vs, 1, &VERTEX_SHADER_SOURCE, NULL);
    glShaderSource(fs, 1, &FRAGMENT_SHADER_SOURCE, NULL);

    glCompileShader(vs);
    glCompileShader(fs);

    wtk_int32_t vs_compiled_successfully;
    wtk_int32_t fs_compiled_successfully;

    const char *vs_compile_log = NULL;
    const char *fs_compile_log = NULL;

    glGetShaderiv(vs, GL_COMPILE_STATUS, &vs_compiled_successfully);
    glGetShaderiv(fs, GL_COMPILE_STATUS, &fs_compiled_successfully);

    if (!vs_compiled_successfully) {
      wtk_int32_t length;
      glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &length);

      char *log = (char *)wtk_block_allocate_s(&r->transient, length + 1);
      glGetShaderInfoLog(vs, length, NULL, log);

      vs_compile_log = (const char *)log;
    }

    if (!fs_compiled_successfully) {
      wtk_int32_t length;
      glGetShaderiv(fs, GL_INFO_LOG_LENGTH, &length);

      char *log = (char *)wtk_block_allocate_s(&r->transient, length + 1);
      glGetShaderInfoLog(fs, length, NULL, log);

      fs_compile_log = (const char *)log;
    }

    wtk_assert_release(vs_compiled_successfully && fs_compiled_successfully);

    glAttachShader(r->program, vs);
    glAttachShader(r->program, fs);

    glLinkProgram(r->program);

    wtk_int32_t program_linked_successfully;
    const char *program_link_log = NULL;

    glGetProgramiv(r->program, GL_LINK_STATUS, &program_linked_successfully);

    if (!program_linked_successfully) {
      wtk_int32_t length;
      glGetProgramiv(r->program, GL_INFO_LOG_LENGTH, &length);

      char *log = (char *)wtk_block_allocate_s(&r->transient, length + 1);
      glGetProgramInfoLog(r->program, length, NULL, log);

      program_link_log = (const char *)log;
    }

    wtk_assert_debug(program_linked_successfully);

    glDetachShader(r->program, vs);
    glDetachShader(r->program, fs);

    glDeleteShader(vs);
    glDeleteShader(fs);

    glUseProgram(r->program);
    glUseProgram(0);
  }

  r->batch_uniform_loc = glGetUniformLocation(r->program, "batch");
  r->dimensions_uniform_loc = glGetUniformLocation(r->program, "dimensions");
  r->debug_uniform_loc = glGetUniformLocation(r->program, "debug");

#if 0
  glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &r->textures);

  if (r->textures > 8)
    /* Hard-limit to 8. Shouldn't need more because we use atlases. */
    r->textures = 8;

  /* HACK(mtwilliams): Limit batches to one texture to reduce impact of lookup
   * for each primitive, until a cheap (branchless?) lookup is implemented. */
  r->textures = 1;
#endif
}

void wtk_renderer_shutdown(void)
{
  glDeleteProgram(r->program);

  wtk_ogl_shutdown();

  wtk_free((void *)r->permanent.base);
  wtk_free((void *)r->transient.base);

  wtk_free((void *)r);

  r = NULL;
}

void wtk_renderer_begin(void)
{
  /* Blow away allocations from previous frame. */
  wtk_block_reset(&r->transient);
}

void wtk_renderer_end(void)
{
  r->frames += 1;
}

void wtk_renderer_render(const wtk_canvas_t *canvas)
{
  wtk_renderer_begin();

  glEnable(GL_SCISSOR_TEST);

  glEnable(GL_BLEND);

  glEnable(GL_CULL_FACE);
  glFrontFace(GL_CW);
  glCullFace(GL_BACK);

  glViewport(0, 0, canvas->width, canvas->height);
  glScissor(0, 0, canvas->width, canvas->height);

  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT);

  glUseProgram(r->program);

  /* Debug visualization is done by our shader. */
  glUniform1ui(r->debug_uniform_loc, 0);

  /* TODO(mtwilliams): Use rectangle texture? */
  glUniform2ui(r->dimensions_uniform_loc, canvas->width, canvas->height);

  glEnableVertexAttribArray(0);
  glEnableVertexAttribArray(1);
  glEnableVertexAttribArray(2);

#if 0
  glEnableVertexAttribArray(3);
#endif

  /* Submit all batches. */
  for (const wtk_batch_t *batch = canvas->batches; batch; batch = batch->next) {
    glUniform1ui(r->batch_uniform_loc, batch->id);

    glScissor(batch->clip.x,
              canvas->height - (batch->clip.h + batch->clip.y),
              batch->clip.w,
              batch->clip.h);

  #if 0
    for (unsigned slot = 0; slot < r->textures; ++slot) {
      glActiveTexture(GL_TEXTURE_0 + slot);
      glBindTexture(GL_TEXTURE_2D, batch->textures[slot] ? batch->textures[slot]->id : 0);
    }
  #endif

    wtk_uint32_t buffer;

    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, batch->count * sizeof(wtk_vertex_t), &batch->verticies[0], GL_STREAM_DRAW);

    glVertexAttribPointer(0, 2, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(wtk_vertex_t), (const void *)offsetof(wtk_vertex_t, x));
    glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(wtk_vertex_t), (const void *)offsetof(wtk_vertex_t, u));
    glVertexAttribPointer(2, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(wtk_vertex_t), (const void *)offsetof(wtk_vertex_t, color));

  #if 0
    glVertexAttribIPointer(4, 1, GL_UNSIGNED_BYTE, sizeof(wtk_vertex_t), (const void *)offsetof(wtk_vertex_t, texture));
  #endif

    glDrawArrays(GL_TRIANGLES, 0, batch->count);

    glDeleteBuffers(1, &buffer);
  }

  wtk_renderer_end();
}

WTK_END_EXTERN_C

repo_name: origamicomet/wtk

repo_language: C

mime_type: text/x-c


text:
/*===-- wtk/render.c ----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#include "wtk/app.h"

#include "wtk/window.h"
#include "wtk/render.h"

#if WTK_PLATFORM == WTK_PLATFORM_WINDOWS
  #include <windows.h>
#elif WTK_PLATFORM == WTK_PLATFORM_MAC
#elif WTK_PLATFORM == WTK_PLATFORM_LINUX
#endif

/* TODO(mtwilliams): Handle overlap by delaying hit tests by one frame. */

/*
  Frames
   Retained mode quad-tree of `frames`.
    Calls to user specified function to perform presentation.
   Maps `n` frames to `m` windows.
    Seamless tabs and docking!
  Widgets
   Immediate mode.
  Canvas
   Immediate mode.
    Dirty tracking to reduce redraw.
*/

WTK_BEGIN_EXTERN_C

typedef struct wtk_app {
#if 0
  wtk_frame_t *frames;
#endif
} wtk_app_t;

static wtk_app_t *app = NULL;

void wtk_app_init(void)
{
  app = (wtk_app_t *)wtk_allocate_s(sizeof(wtk_app_t), 16);

  wtk_renderer_init();
}

void wtk_app_shutdown(void)
{
  wtk_renderer_shutdown();

  wtk_free((void *)app);

  app = NULL;
}

void wtk_app_pump(void)
{
#if WTK_PLATFORM == WTK_PLATFORM_WINDOWS
  /* HACK(mtwilliams): Force redraw. */
#if 0
  for (window in windows)
    InvalidateRect(window->handle, NULL, TRUE);
#endif

  MSG msg;
  while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  /* TODO(mtwilliams): Hide behind flag. */
  /* Wait until messages arrive, or ~16ms elapse. */
  UINT_PTR timer = SetTimer(NULL, NULL, 16, NULL);
  WaitMessage();
  KillTimer(NULL, timer);
#elif WTK_PLATFORM == WTK_PLATFORM_MAC
#elif WTK_PLATFORM == WTK_PLATFORM_LINUX
#endif
}

WTK_END_EXTERN_C


text:
/*===-- wtk/foundation/memory.c -----------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#include "wtk/foundation/memory.h"

#include "wtk/foundation/utilities.h"
#include "wtk/foundation/assert.h"

/* REFACTOR(mtwilliams): Wrap `memset` et al. */
#include <string.h>

#if WTK_COMPILER == WTK_COMPILER_MSVC
  #include <malloc.h>
#endif

WTK_BEGIN_EXTERN_C

void *wtk_allocate(wtk_size_t size,
                   wtk_size_t alignment)
{
  void *ptr;

#if WTK_COMPILER == WTK_COMPILER_MSVC
  ptr = _aligned_malloc(size, alignment);
#else
  #if WTK_PLATFORM == WTK_PLATFORM_MAC || \
      WTK_PLATFORM == WTK_PLATFORM_LINUX
  #endif
#endif

  if (ptr)
    /* We always zero memory, as it prevents an entire class of errors. */
    memset(ptr, 0, size);

  return ptr;
}

void *wtk_allocate_s(wtk_size_t size,
                     wtk_size_t alignment)
{
  void *ptr = wtk_allocate(size, alignment);

  /* Will return `NULL` if out of memory. */
  wtk_assert_release(ptr != NULL);

  return ptr;
}

void wtk_free(void *ptr)
{
  wtk_assert_paranoid(ptr != NULL);

#if WTK_COMPILER == WTK_COMPILER_MSVC
  _aligned_free(ptr);
#else
  #if WTK_PLATFORM == WTK_PLATFORM_MAC || \
      WTK_PLATFORM == WTK_PLATFORM_LINUX
  #endif
#endif
}

void *wtk_block_allocate(wtk_block_t *block,
                         wtk_size_t size)
{
  void *ptr;

  wtk_assert_paranoid(block != NULL);

  /* Allocations are rounded up to the closest multiple of 16, thereby
     ensuring 16-byte alignment. */
  size = WTK_ALIGN_TO_BOUNDARY(size, 16);

  /* May have been given poorly aligned memory... */
  wtk_assert_paranoid(((block->base + block->offset) % 16) == 0);

  if ((block->offset + size) > block->size)
    /* Not enough space. */
    return NULL;

  ptr = (void *)(block->base + block->offset);
  block->offset += size;
  return ptr;
}

void *wtk_block_allocate_s(wtk_block_t *block,
                           wtk_size_t size)
{
  void *ptr;

  wtk_assert_paranoid(block != NULL);

  ptr = wtk_block_allocate(block, size);

  /* Will return `NULL` if out of space. */
  wtk_assert_release(ptr != NULL);

  return ptr;
}

void wtk_block_deallocate(wtk_block_t *block,
                          void *ptr)
{
  wtk_assert_paranoid(block != NULL);
  wtk_assert_paranoid(ptr != NULL);

  wtk_assert_debug((wtk_uintptr_t)ptr >= (block->base));
  wtk_assert_debug((wtk_uintptr_t)ptr <= (block->base + block->offset));

  /* We can't actually free memory. */
}

void wtk_block_reset(wtk_block_t *block)
{
  wtk_assert_paranoid(block != NULL);

  block->offset = 0;

  /* Rezero. Again, to prevent an entire class of errors. */
  memset((void *)block->base, 0, block->size);
}

WTK_END_EXTERN_C


text:
/*===-- wtk/foundation/assert.c -----------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#include "wtk/foundation/assert.h"


text:
/*===-- wtk.h -----------------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_H_
#define _WTK_H_

#include "wtk/config.h"
#include "wtk/linkage.h"

#include "wtk/foundation.h"

#include "wtk/handle.h"

#include "wtk/color.h"

#include "wtk/app.h"

#include "wtk/layout.h"

#include "wtk/window.h"
#include "wtk/frame.h"
#include "wtk/widget.h"

#include "wtk/canvas.h"

#endif /* _WTK_H_ */


text:
/*===-- wtk/app.h -------------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_APP_H_
#define _WTK_APP_H_

#include "wtk/foundation.h"

WTK_BEGIN_EXTERN_C

extern WTK_PUBLIC
  void wtk_app_init(void);

extern WTK_PUBLIC
  void wtk_app_shutdown(void);

extern WTK_PUBLIC
  void wtk_app_pump(void);

WTK_END_EXTERN_C

#endif /* _WTK_APP_H_ */


text:
/*===-- wtk/color.h -----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_COLOR_H_
#define _WTK_COLOR_H_

#include "wtk/foundation.h"

WTK_BEGIN_EXTERN_C

/* See `wtk/types.h` for `wtk_color_t` definition. */

static WTK_INLINE wtk_color_t wtk_rgba(wtk_uint8_t r,
                                       wtk_uint8_t g,
                                       wtk_uint8_t b,
                                       wtk_uint8_t a)
{
  wtk_color_t color;

  color.rgba = ((wtk_uint32_t)a << 24)
             | ((wtk_uint32_t)b << 16)
             | ((wtk_uint32_t)g << 8)
             | ((wtk_uint32_t)r << 0);

  return color;
}

static WTK_INLINE wtk_color_t wtk_rgb(wtk_uint8_t r,
                                      wtk_uint8_t g,
                                      wtk_uint8_t b)
{
  return wtk_rgba(r, g, b, 255);
}

static WTK_INLINE wtk_color_t wtk_rgbaf(wtk_float32_t r,
                                        wtk_float32_t g,
                                        wtk_float32_t b,
                                        wtk_float32_t a)
{
  return wtk_rgba(WTK_CLAMP(r, 0.f, 1.f) * 255.f,
                  WTK_CLAMP(g, 0.f, 1.f) * 255.f,
                  WTK_CLAMP(b, 0.f, 1.f) * 255.f,
                  WTK_CLAMP(a, 0.f, 1.f) * 255.f);
}

static WTK_INLINE wtk_color_t wtk_rgbf(wtk_float32_t r,
                                       wtk_float32_t g,
                                       wtk_float32_t b)
{
  return wtk_rgb(WTK_CLAMP(r, 0.f, 1.f) * 255.f,
                 WTK_CLAMP(g, 0.f, 1.f) * 255.f,
                 WTK_CLAMP(b, 0.f, 1.f) * 255.f);
}

WTK_END_EXTERN_C

#endif /* _WTK_COLOR_H_ */


text:
/*===-- wtk/canvas.h ----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_CANVAS_H_
#define _WTK_CANVAS_H_

#include "wtk/foundation.h"

WTK_BEGIN_EXTERN_C

typedef struct wtk_canvas {
  /*! Dimensions. */
  wtk_uint32_t width;
  wtk_uint32_t height;

  /*! Clipping stack. */
  wtk_rectangle_t clip[8];
  wtk_uint32_t depth;

  /*! Linked-list of batches to submit. */
  struct wtk_batch *batches;

  /*! Current batch. */
  struct wtk_batch *batch;

  /*! Current batch for each level in clipping stack. */
  struct wtk_batch *batch_at_depth[8];

  /*! Allocations for lifetime of canvas. */
  wtk_block_t permanent;

  /*! Allocations for lifetime of a frame. */
  wtk_block_t transient;

  /*! Indicates if a canvas is being drawn to. */
  unsigned drawing;
} wtk_canvas_t;

extern WTK_PUBLIC
  wtk_canvas_t *wtk_canvas_create(
    wtk_uint32_t width,
    wtk_uint32_t height,
    wtk_uint32_t flags);

extern WTK_PUBLIC
  void wtk_canvas_destroy(
    wtk_canvas_t *canvas);

extern WTK_PUBLIC
  void wtk_canvas_begin(
    wtk_canvas_t *canvas);

extern WTK_PUBLIC
  void wtk_canvas_end(
    wtk_canvas_t *canvas);

extern WTK_PUBLIC
  void wtk_canvas_push(
    wtk_canvas_t *canvas,
    wtk_rectangle_t clip);

extern WTK_PUBLIC
  void wtk_canvas_pop(
    wtk_canvas_t *canvas);

extern WTK_PUBLIC
  void wtk_canvas_rect(
    wtk_canvas_t *canvas,
    wtk_rectangle_t rectangle,
    wtk_color_t color,
    wtk_uint32_t flags);

WTK_END_EXTERN_C

#endif /* _WTK_CANVAS_H_ */


text:
/*===-- wtk/handle.h ----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_HANDLE_H_
#define _WTK_HANDLE_H_

#include "wtk/foundation.h"

WTK_BEGIN_EXTERN_C

#if WTK_ARCHITECTURE == WTK_ARCHITECTURE_X86
  typedef wtk_uint32_t wtk_handle_t;

  #define WTK_INVALID_HANDLE ((wtk_handle_t)0)

  #define WTK_HANDLE_TYPE_MASK ((wtk_handle_t)0x0000000Ful)
  #define WTK_HANDLE_ID_MASK ((wtk_handle_t)0xFFFFFFF0ul)
#elif WTK_ARCHITECTURE == WTK_ARCHITECTURE_X86_64
  typedef wtk_uint64_t wtk_handle_t;

  #define WTK_INVALID_HANDLE ((wtk_handle_t)0)

  #define WTK_HANDLE_TYPE_MASK ((wtk_handle_t)0x000000000000000Full)
  #define WTK_HANDLE_ID_MASK ((wtk_handle_t)0xFFFFFFFFFFFFFFF0ull)
#endif

typedef enum wtk_handle_type {
  WTK_WINDOW_HANDLE = 1,
  WTK_FRAME_HANDLE  = 2
} wtk_handle_type_t;

WTK_END_EXTERN_C

#endif /* _WTK_HANDLE_H_ */


text:
/*===-- wtk/frame.h -----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_FRAME_H_
#define _WTK_FRAME_H_

#include "wtk/foundation.h"

WTK_BEGIN_EXTERN_C

typedef struct wtk_frame {
  wtk_rectangle_t footprint;
} wtk_frame_t;

WTK_END_EXTERN_C

#endif /* _WTK_FRAME_H_ */


text:
/*===-- wtk/render.h ----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_RENDER_H_
#define _WTK_RENDER_H_

#include "wtk/foundation.h"

#include "wtk/canvas.h"

WTK_BEGIN_EXTERN_C

extern WTK_PRIVATE
  void wtk_renderer_init(void);

extern WTK_PRIVATE
  void wtk_renderer_shutdown(void);

extern WTK_PRIVATE
  void wtk_renderer_render(
    const wtk_canvas_t *canvas);

WTK_END_EXTERN_C

#endif /* _WTK_RENDER_H_ */


text:
/*===-- wtk/draw.h ------------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_DRAW_H_
#define _WTK_DRAW_H_

#include "wtk/foundation.h"

WTK_BEGIN_EXTERN_C

#if WTK_ARCHITECTURE == WTK_ARCHITECTURE_X86 || \
    WTK_ARCHITECTURE == WTK_ARCHITECTURE_X86_X64
  /* Reduce bloat at cost of unaligned access. */
  #pragma pack(push, 1)
#endif

typedef struct wtk_vertex {
  wtk_uint16_t x, y;
  wtk_uint16_t u, v;
  wtk_uint32_t color;
  wtk_uint8_t  texture;
} wtk_vertex_t;

#if WTK_ARCHITECTURE == WTK_ARCHITECTURE_X86 || \
    WTK_ARCHITECTURE == WTK_ARCHITECTURE_X86_X64
  #pragma pack(pop)
#endif

typedef struct wtk_batch {
  struct wtk_batch *next;

  wtk_uint32_t id;

  /* Timestamps. */
  wtk_uint64_t started;
  wtk_uint64_t completed;

  wtk_rectangle_t clip;

  /* TODO(mtwilliams): Different blend modes? */
#if 0
  wtk_blend_t blend;
#endif

  /* TODO(mtwilliams): Texturing. */
#if 0
  /* Textures applied to primitives. */
  wtk_texture_set_t ts;
#endif

  /* Number of verticies. */
  wtk_uint32_t count;

  /* Maximum number of verticies until you need to start a new batch. */
  wtk_uint32_t limit;

  wtk_vertex_t verticies[0];
} wtk_batch_t;

WTK_END_EXTERN_C

#endif /* _WTK_DRAW_H_ */


text:
/*===-- wtk/gl.h --------------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_GL_H_
#define _WTK_GL_H_

#include "wtk/foundation.h"

/*
 * General
 */

#define GL_MAJOR_VERSION                  0x821B
#define GL_MINOR_VERSION                  0x821C

#define GL_EXTENSIONS                     0x1F03
#define GL_NUM_EXTENSIONS                 0x821D

#define GL_TRUE                           1
#define GL_FALSE                          0

#define GL_NONE                           0
#define GL_FRONT                          0x0404
#define GL_BACK                           0x0405
#define GL_FRONT_AND_BACK                 0x0408

/*
 * Capabilities
 */

#define GL_CULL_FACE                      0x0B44

#define GL_BLEND                          0x0BE2

#define GL_DEPTH_TEST                     0x0B71
#define GL_STENCIL_TEST                   0x0B90
#define GL_SCISSOR_TEST                   0x0C11

#define GL_FRAMEBUFFER_SRGB               0x8DB9

/*
 * Debug
 */

#define GL_DEBUG_OUTPUT                   0x92E0
#define GL_DEBUG_OUTPUT_SYNCHRONOUS       0x8242

#define GL_DEBUG_CALLBACK_FUNCTION        0x8244
#define GL_DEBUG_CALLBACK_USER_PARAM      0x8245

#define GL_DEBUG_SOURCE_API               0x8246
#define GL_DEBUG_SOURCE_WINDOW_SYSTEM     0x8247
#define GL_DEBUG_SOURCE_SHADER_COMPILER   0x8248
#define GL_DEBUG_SOURCE_THIRD_PARTY       0x8249
#define GL_DEBUG_SOURCE_APPLICATION       0x824A
#define GL_DEBUG_SOURCE_OTHER             0x824B

#define GL_DEBUG_TYPE_ERROR               0x824C
#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR  0x824E
#define GL_DEBUG_TYPE_PORTABILITY         0x824F
#define GL_DEBUG_TYPE_PERFORMANCE         0x8250
#define GL_DEBUG_TYPE_OTHER               0x8251
#define GL_DEBUG_TYPE_MARKER              0x8268

#define GL_DEBUG_TYPE_PUSH_GROUP          0x8269
#define GL_DEBUG_TYPE_POP_GROUP           0x826A

#define GL_DEBUG_SEVERITY_HIGH            0x9146
#define GL_DEBUG_SEVERITY_MEDIUM          0x9147
#define GL_DEBUG_SEVERITY_LOW             0x9148
#define GL_DEBUG_SEVERITY_NOTIFICATION    0x826B

/*
 * Types
 */

#define GL_BYTE                           0x1400
#define GL_UNSIGNED_BYTE                  0x1401
#define GL_SHORT                          0x1402
#define GL_UNSIGNED_SHORT                 0x1403
#define GL_INT                            0x1404
#define GL_UNSIGNED_INT                   0x1405
#define GL_HALF_FLOAT                     0x140B
#define GL_FLOAT                          0x1406
#define GL_DOUBLE                         0x140A

/*
 * Windings
 */

#define GL_CW                             0x0900
#define GL_CCW                            0x0901

/*
 * Polygon Modes
 */

#define GL_POINT                          0x1B00
#define GL_LINE                           0x1B01
#define GL_FILL                           0x1B02

/*
 * Functions
 */

#define GL_FUNC_ADD                       0x8006
#define GL_FUNC_SUBTRACT                  0x800A
#define GL_FUNC_REVERSE_SUBTRACT          0x800B
#define GL_MIN                            0x8007
#define GL_MAX                            0x8008

/*
 * Operations
 */

#define GL_CLEAR                          0x1500
#define GL_AND                            0x1501
#define GL_AND_REVERSE                    0x1502
#define GL_COPY                           0x1503
#define GL_AND_INVERTED                   0x1504
#define GL_NOOP                           0x1505
#define GL_XOR                            0x1506
#define GL_OR                             0x1507
#define GL_NOR                            0x1508
#define GL_EQUIV                          0x1509
#define GL_INVERT                         0x150A
#define GL_OR_REVERSE                     0x150B
#define GL_COPY_INVERTED                  0x150C
#define GL_OR_INVERTED                    0x150D
#define GL_NAND                           0x150E
#define GL_SET                            0x150F
#define GL_KEEP                           0x1E00
#define GL_REPLACE                        0x1E01
#define GL_INCR                           0x1E02
#define GL_DECR                           0x1E03
#define GL_INCR_WRAP                      0x8507
#define GL_DECR_WRAP                      0x8508

/*
 * Comparisons
 */

#define GL_NEVER                          0x0200
#define GL_LESS                           0x0201
#define GL_EQUAL                          0x0202
#define GL_LEQUAL                         0x0203
#define GL_GREATER                        0x0204
#define GL_NOT_EQUAL                      0x0205
#define GL_GEQUAL                         0x0206
#define GL_ALWAYS                         0x0207

/*
 * Equations
 */

#define GL_ZERO                           0x0000
#define GL_ONE                            0x0001
#define GL_SRC_COLOR                      0x0300
#define GL_ONE_MINUS_SRC_COLOR            0x0301
#define GL_SRC_ALPHA                      0x0302
#define GL_ONE_MINUS_SRC_ALPHA            0x0303
#define GL_DST_ALPHA                      0x0304
#define GL_ONE_MINUS_DST_ALPHA            0x0305
#define GL_DST_COLOR                      0x0306
#define GL_ONE_MINUS_DST_COLOR            0x0307
#define GL_SRC_ALPHA_SATURATE             0x0308
#define GL_CONSTANT_COLOR                 0x8001
#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002

/*
 * Formats
 */

#define GL_RED                            0x1903
#define GL_RG                             0x8227
#define GL_RGB                            0x1907
#define GL_RGBA                           0x1908

#define GL_DEPTH_COMPONENT                0x1902
#define GL_DEPTH_STENCIL                  0x84F9

#define GL_R8                             0x8229
#define GL_R16F                           0x822D
#define GL_R32F                           0x822E
#define GL_R8I                            0x8231
#define GL_R16I                           0x8233
#define GL_R32I                           0x8235
#define GL_R8UI                           0x8232
#define GL_R16UI                          0x8234
#define GL_R32UI                          0x8236
#define GL_RG8                            0x822B
#define GL_RG16F                          0x822F
#define GL_RG32F                          0x8230
#define GL_RG8I                           0x8237
#define GL_RG16I                          0x8239
#define GL_RG32I                          0x823B
#define GL_RG8UI                          0x8238
#define GL_RG16UI                         0x823A
#define GL_RG32UI                         0x823C
#define GL_RGB16F                         0x881B
#define GL_RGB32F                         0x8815
#define GL_RGB32I                         0x8D83
#define GL_RGB32UI                        0x8D71
#define GL_RGB8                           0x8051
#define GL_RGBA8                          0x8058
#define GL_RGBA16F                        0x881A
#define GL_RGBA32F                        0x8814
#define GL_RGBA8I                         0x8D8E
#define GL_RGBA16I                        0x8D88
#define GL_RGBA32I                        0x8D82
#define GL_RGBA8UI                        0x8D7C
#define GL_RGBA16UI                       0x8D76
#define GL_RGBA32UI                       0x8D70

#define GL_BGR                            0x80E0
#define GL_BGRA                           0x80E1

#define GL_SRGB8                          0x8C41
#define GL_SRGB8_ALPHA8                   0x8C43

#define GL_DEPTH_COMPONENT16              0x81A5
#define GL_DEPTH_COMPONENT24              0x81A6
#define GL_DEPTH_COMPONENT32              0x81A7

#define GL_DEPTH24_STENCIL8               0x88F0

/*
 * Buffers
 */

#define GL_BUFFER                         0x82E0

#define GL_ARRAY_BUFFER                   0x8892
#define GL_ELEMENT_ARRAY_BUFFER           0x8893
#define GL_UNIFORM_BUFFER                 0x8A11

#define GL_STATIC_DRAW                    0x88E4
#define GL_STREAM_DRAW                    0x88E0
#define GL_DYNAMIC_DRAW                   0x88E8

#define GL_MAP_READ_BIT                   0x0001
#define GL_MAP_WRITE_BIT                  0x0002

/*
 * Textures
 */

#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872

#define GL_TEXTURE                        0x1702

#define GL_TEXTURE_0                      0x84C0
#define GL_TEXTURE_1                      0x84C1
#define GL_TEXTURE_2                      0x84C2
#define GL_TEXTURE_3                      0x84C3
#define GL_TEXTURE_4                      0x84C4
#define GL_TEXTURE_5                      0x84C5
#define GL_TEXTURE_6                      0x84C6
#define GL_TEXTURE_7                      0x84C7
#define GL_TEXTURE_8                      0x84C8

#define GL_TEXTURE_1D                     0x0DE0
#define GL_TEXTURE_2D                     0x0DE1
#define GL_TEXTURE_3D                     0x806F

#define GL_TEXTURE_1D_ARRAY               0x8C18
#define GL_TEXTURE_2D_ARRAY               0x8C1A

#define GL_TEXTURE_MAG_FILTER             0x2800
#define GL_TEXTURE_MIN_FILTER             0x2801

#define GL_TEXTURE_WRAP_S                 0x2802
#define GL_TEXTURE_WRAP_T                 0x2803
#define GL_TEXTURE_WRAP_R                 0x8072

/*
 * Filters
 */

#define GL_NEAREST                        0x2600
#define GL_LINEAR                         0x2601
#define GL_NEAREST_MIPMAP_NEAREST         0x2700
#define GL_LINEAR_MIPMAP_NEAREST          0x2701
#define GL_NEAREST_MIPMAP_LINEAR          0x2702
#define GL_LINEAR_MIPMAP_LINEAR           0x2703

/*
 * Wrapping
 */

#define GL_REPEAT                         0x2901
#define GL_MIRRORED_REPEAT                0x8370
#define GL_CLAMP_TO_EDGE                  0x812F
#define GL_CLAMP_TO_BORDER                0x812D

/*
 * Shaders
 */

#define GL_SHADER                         0x82E1
#define GL_PROGRAM                        0x82E2

#define GL_VERTEX_SHADER                  0x8B31
#define GL_FRAGMENT_SHADER                0x8B30

#define GL_COMPILE_STATUS                 0x8B81
#define GL_LINK_STATUS                    0x8B82
#define GL_VALIDATE_STATUS                0x8B83
#define GL_DELETE_STATUS                  0x8B80

#define GL_INFO_LOG_LENGTH                0x8B84

/*
 * Targets
 */

#define GL_FRAMEBUFFER                    0x8D40
#define GL_READ_FRAMEBUFFER               0x8CA8
#define GL_DRAW_FRAMEBUFFER               0x8CA9

#define GL_COLOR_ATTACHMENT               0x8CE0
#define GL_DEPTH_ATTACHMENT               0x8D00
#define GL_STENCIL_ATTACHMENT             0x8D20
#define GL_DEPTH_STENCIL_ATTACHMENT       0x821A

#define GL_COLOR                          0x1800
#define GL_DEPTH                          0x1801
#define GL_STENCIL                        0x1802

#define GL_DEPTH_BUFFER_BIT               0x00000100
#define GL_STENCIL_BUFFER_BIT             0x00000400
#define GL_COLOR_BUFFER_BIT               0x00004000

#define GL_DRAW_BUFFER                    0x8825

/*
 * Topology
 */

#define GL_POINTS                         0x0000
#define GL_LINES                          0x0001
#define GL_LINE_LOOP                      0x0002
#define GL_LINE_STRIP                     0x0003
#define GL_TRIANGLES                      0x0004
#define GL_TRIANGLE_STRIP                 0x0005
#define GL_TRIANGLE_FAN                   0x0006

WTK_BEGIN_EXTERN_C

/*
 * Imports
 */

#if WTK_PLATFORM == WTK_PLATFORM_WINDOWS
  /* Decorator for dynamic imports. */
  #define GL_ENTRY_POINT __stdcall
#endif

typedef void (GL_ENTRY_POINT *GLPUSHDEBUGGROUPPROC)(wtk_uint32_t source, wtk_uint32_t id, wtk_uint32_t length, const char *label);
typedef void (GL_ENTRY_POINT *GLPOPDEBUGGROUPPROC)(void);

extern GLPUSHDEBUGGROUPPROC glPushDebugGroup;
extern GLPOPDEBUGGROUPPROC glPopDebugGroup;

typedef void (GL_ENTRY_POINT *GLOBJECTLABELPROC)(wtk_uint32_t identifier, wtk_uint32_t name, wtk_uint32_t length, const char *label);

extern GLOBJECTLABELPROC glObjectLabel;

typedef void (GL_ENTRY_POINT *GLFRAMETERMINATORGREMEDYPROC)(void);

extern GLFRAMETERMINATORGREMEDYPROC glFrameTerminatorGREMEDY;

typedef void (GL_ENTRY_POINT *GLGETBOOLEANVPROC)(wtk_uint32_t parameter, wtk_uint32_t *value);
typedef void (GL_ENTRY_POINT *GLGETINTEGERVPROC)(wtk_uint32_t parameter, wtk_int32_t *value);
typedef void (GL_ENTRY_POINT *GLGETFLOATVPROC)(wtk_uint32_t parameter, wtk_float32_t *value);
typedef void (GL_ENTRY_POINT *GLGETDOUBLEVPROC)(wtk_uint32_t parameter, wtk_float64_t *value);
typedef const char *(GL_ENTRY_POINT *GLGETSTRINGPROC)(wtk_uint32_t name);

extern GLGETBOOLEANVPROC glGetBooleanv;
extern GLGETINTEGERVPROC glGetIntegerv;
extern GLGETFLOATVPROC glGetFloatv;
extern GLGETDOUBLEVPROC glGetDoublev;
extern GLGETSTRINGPROC glGetString;

typedef void (GL_ENTRY_POINT *GLENABLEPROC)(wtk_uint32_t capability);
typedef void (GL_ENTRY_POINT *GLDISABLEPROC)(wtk_uint32_t capability);

extern GLENABLEPROC  glEnable;
extern GLDISABLEPROC glDisable;

typedef void (GL_ENTRY_POINT *GLPOLYGONMODEPROC)(wtk_uint32_t face, wtk_uint32_t mode);

extern GLPOLYGONMODEPROC glPolygonMode;

typedef void (GL_ENTRY_POINT *GLFRONTFACEPROC)(wtk_uint32_t mode);
typedef void (GL_ENTRY_POINT *GLCULLFACEPROC)(wtk_uint32_t mode);

extern GLFRONTFACEPROC glFrontFace;
extern GLCULLFACEPROC glCullFace;

typedef void (GL_ENTRY_POINT *GLBLENDFUNCSEPARATEPROC)(wtk_uint32_t src_factor_rgb, wtk_uint32_t dst_factor_rgb, wtk_uint32_t src_factor_alpha, wtk_uint32_t dst_factor_alpha);
typedef void (GL_ENTRY_POINT *GLBLENDEQUATIONSEPARATEPROC)(wtk_uint32_t rgb, wtk_uint32_t alpha);
typedef void (GL_ENTRY_POINT *GLBLENDCOLORPROC)(wtk_float32_t red, wtk_float32_t green, wtk_float32_t blue, wtk_float32_t alpha);

extern GLBLENDFUNCSEPARATEPROC glBlendFuncSeparate;
extern GLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate;
extern GLBLENDCOLORPROC glBlendColor;

typedef void (GL_ENTRY_POINT *GLCOLORMASKPROC)(wtk_uint32_t r, wtk_uint32_t g, wtk_uint32_t b, wtk_uint32_t a);

extern GLCOLORMASKPROC glColorMask;

typedef void (GL_ENTRY_POINT *GLDEPTHFUNCPROC)(wtk_uint32_t func);
typedef void (GL_ENTRY_POINT *GLDEPTHMASKPROC)(wtk_uint32_t flag);

extern GLDEPTHFUNCPROC glDepthFunc;
extern GLDEPTHMASKPROC glDepthMask;

typedef void (GL_ENTRY_POINT *GLSTENCILOPSEPARATEPROC)(wtk_uint32_t face, wtk_uint32_t sfail, wtk_uint32_t dpfail, wtk_uint32_t dppass);
typedef void (GL_ENTRY_POINT *GLSTENCILFUNCSEPARATEPROC)(wtk_uint32_t face, wtk_uint32_t func, wtk_int32_t ref, wtk_uint32_t mask);
typedef void (GL_ENTRY_POINT *GLSTENCILMASKSEPARATEPROC)(wtk_uint32_t face, wtk_uint32_t mask);

extern GLSTENCILOPSEPARATEPROC glStencilOpSeparate;
extern GLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate;
extern GLSTENCILMASKSEPARATEPROC glStencilMaskSeparate;

typedef void (GL_ENTRY_POINT *GLGENBUFFERSPROC)(wtk_uint32_t n, wtk_uint32_t *buffers);
typedef void (GL_ENTRY_POINT *GLGENTEXTURESPROC)(wtk_uint32_t n, wtk_uint32_t *textures);
typedef void (GL_ENTRY_POINT *GLGENFRAMEBUFFERSPROC)(wtk_uint32_t n, wtk_uint32_t *framebuffers);
typedef wtk_uint32_t (GL_ENTRY_POINT *GLCREATESHADERPROC)(wtk_uint32_t type);
typedef wtk_uint32_t (GL_ENTRY_POINT *GLCREATEPROGRAMPROC)(void);

extern GLGENBUFFERSPROC glGenBuffers;
extern GLGENTEXTURESPROC glGenTextures;
extern GLGENFRAMEBUFFERSPROC glGenFramebuffers;
extern GLCREATESHADERPROC glCreateShader;
extern GLCREATEPROGRAMPROC glCreateProgram;

typedef void (GL_ENTRY_POINT *GLDELETEBUFFERSPROC)(wtk_uint32_t n, const wtk_uint32_t *buffers);
typedef void (GL_ENTRY_POINT *GLDELETETEXTURESPROC)(wtk_uint32_t n, const wtk_uint32_t *textures);
typedef void (GL_ENTRY_POINT *GLDELETESHADERPROC)(wtk_uint32_t shader);
typedef void (GL_ENTRY_POINT *GLDELETEPROGRAMPROC)(wtk_uint32_t program);
typedef void (GL_ENTRY_POINT *GLDELETEFRAMEBUFFERSPROC)(wtk_uint32_t n, const wtk_uint32_t *framebuffers);

extern GLDELETEBUFFERSPROC glDeleteBuffers;
extern GLDELETETEXTURESPROC glDeleteTextures;
extern GLDELETESHADERPROC glDeleteShader;
extern GLDELETEPROGRAMPROC glDeleteProgram;
extern GLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;

typedef void (GL_ENTRY_POINT *GLVIEWPORTPROC)(wtk_int32_t x, wtk_int32_t y, wtk_int32_t w, wtk_int32_t h);
typedef void (GL_ENTRY_POINT *GLSCISSORPROC)(wtk_int32_t x, wtk_int32_t y, wtk_int32_t w, wtk_int32_t h);

extern GLVIEWPORTPROC glViewport;
extern GLSCISSORPROC  glScissor;

typedef void (GL_ENTRY_POINT *GLBINDBUFFERPROC)(wtk_uint32_t target, wtk_uint32_t buffer);

extern GLBINDBUFFERPROC glBindBuffer;

typedef void (GL_ENTRY_POINT *GLBUFFERDATAPROC)(wtk_uint32_t target, wtk_size_t size, const void *data, wtk_uint32_t usage);
typedef void (GL_ENTRY_POINT *GLBUFFERSUBDATAPROC)(wtk_uint32_t target, wtk_uintptr_t offset, wtk_size_t length, const void *data);

extern GLBUFFERDATAPROC glBufferData;
extern GLBUFFERSUBDATAPROC glBufferSubData;

typedef void *(GL_ENTRY_POINT *GLMAPBUFFERPROC)(wtk_uint32_t target, wtk_uint32_t access);

extern GLMAPBUFFERPROC glMapBuffer;

typedef void (GL_ENTRY_POINT *GLUNMAPBUFFERPROC)(wtk_uint32_t target);

extern GLUNMAPBUFFERPROC glUnmapBuffer;

typedef void (GL_ENTRY_POINT *GLACTIVETEXTUREPROC)(wtk_uint32_t slot);

extern GLACTIVETEXTUREPROC glActiveTexture;

typedef void (GL_ENTRY_POINT *GLBINDTEXTUREPROC)(wtk_uint32_t target, wtk_uint32_t texture);

extern GLBINDTEXTUREPROC glBindTexture;

typedef void (GL_ENTRY_POINT *GLTEXIMAGE1DPROC)(wtk_uint32_t target,
                                                wtk_uint32_t level,
                                                wtk_uint32_t internal_format,
                                                wtk_uint32_t width,
                                                wtk_uint32_t border,
                                                wtk_uint32_t format,
                                                wtk_uint32_t type,
                                                const void *data);

typedef void (GL_ENTRY_POINT *GLTEXIMAGE2DPROC)(wtk_uint32_t target,
                                                wtk_uint32_t level,
                                                wtk_uint32_t internal_format,
                                                wtk_uint32_t width,
                                                wtk_uint32_t height,
                                                wtk_uint32_t border,
                                                wtk_uint32_t format,
                                                wtk_uint32_t type,
                                                const void *data);

typedef void (GL_ENTRY_POINT *GLTEXIMAGE3DPROC)(wtk_uint32_t target,
                                                wtk_uint32_t level,
                                                wtk_uint32_t internal_format,
                                                wtk_uint32_t width,
                                                wtk_uint32_t height,
                                                wtk_uint32_t depth,
                                                wtk_uint32_t border,
                                                wtk_uint32_t format,
                                                wtk_uint32_t type,
                                                const void *data);

extern GLTEXIMAGE1DPROC glTexImage1D;
extern GLTEXIMAGE2DPROC glTexImage2D;
extern GLTEXIMAGE3DPROC glTexImage3D;

typedef void (GL_ENTRY_POINT *GLTEXPARAMETERFPROC)(wtk_uint32_t target, wtk_uint32_t name, wtk_float32_t value);
typedef void (GL_ENTRY_POINT *GLTEXPARAMETERIPROC)(wtk_uint32_t target, wtk_uint32_t name, wtk_int32_t value);

extern GLTEXPARAMETERFPROC glTexParameterf;
extern GLTEXPARAMETERIPROC glTexParameteri;

typedef void (GL_ENTRY_POINT *GLGENERATEMIPMAPPROC)(wtk_uint32_t target);

/* PERF(mtwilliams): Generate manually. Drivers can be really bad at generating mipmaps. */
extern GLGENERATEMIPMAPPROC glGenerateMipmap;

typedef void (GL_ENTRY_POINT *GLSHADERSOURCEPROC)(wtk_uint32_t shader, wtk_uint32_t count, const char * const *sources, const wtk_uint32_t *lengths);
typedef void (GL_ENTRY_POINT *GLCOMPILESHADERPROC)(wtk_uint32_t shader);

extern GLSHADERSOURCEPROC glShaderSource;
extern GLCOMPILESHADERPROC glCompileShader;

typedef void (GL_ENTRY_POINT *GLGETSHADERIVPROC)(wtk_uint32_t shader, wtk_uint32_t pname, wtk_int32_t *params);
typedef void (GL_ENTRY_POINT *GLGETSHADERINFOLOGPROC)(wtk_uint32_t shader, wtk_int32_t size, wtk_int32_t *length, char *buffer);

extern GLGETSHADERIVPROC glGetShaderiv;
extern GLGETSHADERINFOLOGPROC glGetShaderInfoLog;

typedef void (GL_ENTRY_POINT *GLATTACHSHADERPROC)(wtk_uint32_t program, wtk_uint32_t shader);
typedef void (GL_ENTRY_POINT *GLDETACHSHADERPROC)(wtk_uint32_t program, wtk_uint32_t shader);
typedef void (GL_ENTRY_POINT *GLLINKPROGRAMPROC)(wtk_uint32_t program);

extern GLATTACHSHADERPROC glAttachShader;
extern GLDETACHSHADERPROC glDetachShader;
extern GLLINKPROGRAMPROC glLinkProgram;

typedef void (GL_ENTRY_POINT *GLGETPROGRAMIVPROC)(wtk_uint32_t program, wtk_uint32_t pname, wtk_int32_t *params);
typedef void (GL_ENTRY_POINT *GLGETPROGRAMINFOLOGPROC)(wtk_uint32_t program, wtk_int32_t size, wtk_int32_t *length, char *buffer);

extern GLGETPROGRAMIVPROC glGetProgramiv;
extern GLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;

typedef wtk_uint32_t (GL_ENTRY_POINT *GLGETUNIFORMLOCATIONPROC)(wtk_uint32_t program, const char *name);

extern GLGETUNIFORMLOCATIONPROC glGetUniformLocation;

typedef void (GL_ENTRY_POINT *GLUNIFORM1FPROC)(wtk_uint32_t location, wtk_float32_t v0);
typedef void (GL_ENTRY_POINT *GLUNIFORM2FPROC)(wtk_uint32_t location, wtk_float32_t v0, wtk_float32_t v1);
typedef void (GL_ENTRY_POINT *GLUNIFORM3FPROC)(wtk_uint32_t location, wtk_float32_t v0, wtk_float32_t v1, wtk_float32_t v2);
typedef void (GL_ENTRY_POINT *GLUNIFORM4FPROC)(wtk_uint32_t location, wtk_float32_t v0, wtk_float32_t v1, wtk_float32_t v2, wtk_float32_t v3);

typedef void (GL_ENTRY_POINT *GLUNIFORM1IPROC)(wtk_uint32_t location, wtk_uint32_t v0);
typedef void (GL_ENTRY_POINT *GLUNIFORM2IPROC)(wtk_uint32_t location, wtk_int32_t v0, wtk_int32_t v1);
typedef void (GL_ENTRY_POINT *GLUNIFORM3IPROC)(wtk_uint32_t location, wtk_int32_t v0, wtk_int32_t v1, wtk_int32_t v2);
typedef void (GL_ENTRY_POINT *GLUNIFORM4IPROC)(wtk_uint32_t location, wtk_int32_t v0, wtk_int32_t v1, wtk_int32_t v2, wtk_int32_t v3);

typedef void (GL_ENTRY_POINT *GLUNIFORM1UIPROC)(wtk_uint32_t location, wtk_uint32_t v0);
typedef void (GL_ENTRY_POINT *GLUNIFORM2UIPROC)(wtk_uint32_t location, wtk_uint32_t v0, wtk_uint32_t v1);
typedef void (GL_ENTRY_POINT *GLUNIFORM3UIPROC)(wtk_uint32_t location, wtk_uint32_t v0, wtk_uint32_t v1, wtk_uint32_t v2);
typedef void (GL_ENTRY_POINT *GLUNIFORM4UIPROC)(wtk_uint32_t location, wtk_uint32_t v0, wtk_uint32_t v1, wtk_uint32_t v2, wtk_uint32_t v3);

extern GLUNIFORM1FPROC glUniform1f;
extern GLUNIFORM2FPROC glUniform2f;
extern GLUNIFORM3FPROC glUniform3f;
extern GLUNIFORM4FPROC glUniform4f;

extern GLUNIFORM1IPROC glUniform1i;
extern GLUNIFORM2IPROC glUniform2i;
extern GLUNIFORM3IPROC glUniform3i;
extern GLUNIFORM4IPROC glUniform4i;

extern GLUNIFORM1UIPROC glUniform1ui;
extern GLUNIFORM2UIPROC glUniform2ui;
extern GLUNIFORM3UIPROC glUniform3ui;
extern GLUNIFORM4UIPROC glUniform4ui;

typedef void (GL_ENTRY_POINT *GLUSEPROGRAMPROC)(wtk_uint32_t program);

extern GLUSEPROGRAMPROC glUseProgram;

typedef void (GL_ENTRY_POINT *GLENABLEVERTEXATTRIBARRAYPROC)(wtk_uint32_t index);
typedef void (GL_ENTRY_POINT *GLDISABLEVERTEXATTRIBARRAYPROC)(wtk_uint32_t index);

extern GLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
extern GLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;

typedef void (GL_ENTRY_POINT *GLVERTEXATTRIBPOINTERPROC)(wtk_uint32_t index, wtk_uint32_t size, wtk_uint32_t type, wtk_uint32_t normalized, wtk_uint32_t stride, const void *pointer);
typedef void (GL_ENTRY_POINT *GLVERTEXATTRIBIPOINTERPROC)(wtk_uint32_t index, wtk_uint32_t size, wtk_uint32_t type, wtk_uint32_t stride, const void *pointer);
typedef void (GL_ENTRY_POINT *GLVERTEXATTRIBDIVISORPROC)(wtk_uint32_t index, wtk_uint32_t divisor);

extern GLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
extern GLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;

typedef void (GL_ENTRY_POINT *GLBINDFRAMEBUFFERPROC)(wtk_uint32_t target, wtk_uint32_t framebuffer);

extern GLBINDFRAMEBUFFERPROC glBindFramebuffer;

typedef void (GL_ENTRY_POINT *GLFRAMEBUFFERTEXTURE1DPROC)(wtk_uint32_t target,
                                                          wtk_uint32_t attachment,
                                                          wtk_uint32_t textarget,
                                                          wtk_uint32_t texture,
                                                          wtk_uint32_t level);

typedef void (GL_ENTRY_POINT *GLFRAMEBUFFERTEXTURE2DPROC)(wtk_uint32_t target,
                                                          wtk_uint32_t attachment,
                                                          wtk_uint32_t textarget,
                                                          wtk_uint32_t texture,
                                                          wtk_uint32_t level);

typedef void (GL_ENTRY_POINT *GLFRAMEBUFFERTEXTURE3DPROC)(wtk_uint32_t target,
                                                          wtk_uint32_t attachment,
                                                          wtk_uint32_t textarget,
                                                          wtk_uint32_t texture,
                                                          wtk_uint32_t level,
                                                          wtk_uint32_t layer);

extern GLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
extern GLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
extern GLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;

typedef void (GL_ENTRY_POINT *GLDRAWBUFFERPROC)(wtk_uint32_t buffer);
typedef void (GL_ENTRY_POINT *GLDRAWBUFFERSPROC)(wtk_uint32_t n, const wtk_uint32_t *buffers);

extern GLDRAWBUFFERPROC glDrawBuffer;
extern GLDRAWBUFFERSPROC glDrawBuffers;

typedef void (GL_ENTRY_POINT *GLCLEARCOLORPROC)(wtk_float32_t r, wtk_float32_t g, wtk_float32_t b, wtk_float32_t a);
typedef void (GL_ENTRY_POINT *GLCLEARDEPTHPROC)(wtk_float64_t depth);
typedef void (GL_ENTRY_POINT *GLCLEARSTENCILPROC)(wtk_uint32_t stencil);

extern GLCLEARCOLORPROC glClearColor;
extern GLCLEARDEPTHPROC glClearDepth;
extern GLCLEARSTENCILPROC glClearStencil;

typedef void (GL_ENTRY_POINT *GLCLEARPROC)(wtk_uint32_t mask);

extern GLCLEARPROC glClear;

typedef void (GL_ENTRY_POINT *GLDRAWARRAYSPROC)(wtk_uint32_t mode, wtk_uint32_t first, wtk_uint32_t count);
typedef void (GL_ENTRY_POINT *GLDRAWELEMENTSPROC)(wtk_uint32_t mode, wtk_uint32_t count, wtk_uint32_t type, const void *indices);

extern GLDRAWARRAYSPROC glDrawArrays;
extern GLDRAWELEMENTSPROC glDrawElements;

typedef void (GL_ENTRY_POINT *GLBLITFRAMEBUFFERPROC)(wtk_int32_t src_x0,
                                                     wtk_int32_t src_y0,
                                                     wtk_int32_t src_x1,
                                                     wtk_int32_t src_y1,
                                                     wtk_int32_t dst_x0,
                                                     wtk_int32_t dst_y0,
                                                     wtk_int32_t dst_x1,
                                                     wtk_int32_t dst_y1,
                                                     wtk_uint32_t mask,
                                                     wtk_uint32_t filter);

extern GLBLITFRAMEBUFFERPROC glBlitFramebuffer;

typedef void (GL_ENTRY_POINT *GLFLUSHPROC)(void);
typedef void (GL_ENTRY_POINT *GLFINISHPROC)(void);

extern GLFLUSHPROC  glFlush;
extern GLFINISHPROC glFinish;

extern WTK_PRIVATE wtk_uint32_t GL_KHR_debug;
extern WTK_PRIVATE wtk_uint32_t GL_GREMEDY_frame_terminator;

/*
 * Management
 */

extern WTK_PRIVATE
  void wtk_ogl_init(void);

extern WTK_PRIVATE
  void wtk_ogl_shutdown(void);

typedef struct wtk_ogl_surface wtk_ogl_surface_t;

extern WTK_PRIVATE
  wtk_ogl_surface_t *wtk_ogl_create_surface(
    wtk_uintptr_t window);

extern WTK_PRIVATE
  void wtk_ogl_destroy_surface(
    wtk_ogl_surface_t *surface);

extern WTK_PRIVATE
  void wtk_ogl_resize_surface(
    wtk_ogl_surface_t *surface,
    wtk_uint32_t width,
    wtk_uint32_t height);

extern WTK_PRIVATE
  void wtk_ogl_dimensions_of_surface(
    const wtk_ogl_surface_t *surface,
    wtk_uint32_t *width,
    wtk_uint32_t *height);

extern WTK_PRIVATE
  void wtk_ogl_bind(
    wtk_ogl_surface_t *surface);

typedef enum wtk_ogl_present_flags {
  /*! Synchronize to vertical blanks. */
  WTK_OGL_PRESENT_SYNCHRONIZE = (1 << 0)
} wtk_ogl_present_flags_t;

extern WTK_PRIVATE
  void wtk_ogl_present(
    wtk_ogl_surface_t *surface,
    wtk_uint32_t flags);

WTK_END_EXTERN_C

#endif /* _WTK_GL_H_ */


text:
/*===-- wtk/config.h ----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_CONFIG_H_
#define _WTK_CONFIG_H_

/**
 * \def WTK_PARANOID
 * \brief Enables more thorough (and costly) checks.
 */
#ifndef WTK_PARANOID
  #define WTK_PARANOID 0
#endif

/* REFACTOR(mtwilliams): Discard concept of debug and development builds,
 * outside of setting reasonable defaults that can be overridden.
 */

/**
 * \def WTK_CONFIGURATION_DEBUG
 * \brief Debug build.
 */
#define WTK_CONFIGURATION_DEBUG 1

/**
 * \def WTK_CONFIGURATION_DEBUG
 * \brief Release build.
 */
#define WTK_CONFIGURATION_RELEASE 2

/**
 * \def WTK_CONFIGURATION
 * \brief Specifies how "loose and fast" WTK is.
 */
#if defined(DOXYGEN)
  #define WTK_CONFIGURATION
#else
  #if !defined(WTK_CONFIGURATION)
    #error ("No configuration specified! Please specify a configuration by defining `WTK_CONFIGURATION'.")
  #else
    #if (WTK_CONFIGURATION != WTK_CONFIGURATION_DEBUG) && \
        (WTK_CONFIGURATION != WTK_CONFIGURATION_RELEASE)
      #error ("Unknown configuration specified. See include/wtk/config.h for a list of possible configurations.")
    #endif
  #endif
#endif

/**
 * \def WTK_PLATFORM_WINDOWS
 * \brief Windows
 */
#define WTK_PLATFORM_WINDOWS 1

/**
 * \def WTK_PLATFORM_MAC
 * \brief macOS
 */
#define WTK_PLATFORM_MAC 2

/**
 * \def WTK_PLATFORM_LINUX
 * \brief Linux
 */
#define WTK_PLATFORM_LINUX 3

/**
 * \def WTK_PLATFORM
 * \brief Target platform.
 */
#if defined(DOXYGEN)
  #define WTK_PLATFORM
#else
  #if defined(_WIN32) || defined(_WIN64)
    #define WTK_PLATFORM WTK_PLATFORM_WINDOWS
  #elif defined(__APPLE__)
    #include <TargetConditionals.h>
    #if defined(TARGET_OS_IPHONE)
      #define WTK_PLATFORM WTK_PLATFORM_IOS
    #else
      #define WTK_PLATFORM WTK_PLATFORM_MAC
    #endif
  #elif defined(__linux__)
    #if defined(ANDROID)
      #define WTK_PLATFORM WTK_PLATFORM_ANDROID
    #else
      #define WTK_PLATFORM WTK_PLATFORM_LINUX
    #endif
  #else
    #error ("Unknown or unsupported platform!")
  #endif
#endif

/**
 * \def WTK_COMPILER_MSVC
 * \brief Microsoft Visual C/C++
 */
#define WTK_COMPILER_MSVC 1

/**
 * \def WTK_COMPILER_GCC
 * \brief GNU Compiler Collection
 */
#define WTK_COMPILER_GCC 2

/**
 * \def WTK_COMPILER_CLANG
 * \brief LLVM/Clang
 */
#define WTK_COMPILER_CLANG 3

/**
 * \def WTK_COMPILER_CLANG
 * \brief Host compiler.
 */
#if defined(DOXYGEN)
  #define WTK_COMPILER
#else
  #if defined(_MSC_VER)
    #define WTK_COMPILER WTK_COMPILER_MSVC
    #define WTK_MICROSOFT_VISUAL_STUDIO_2013 1800
    #define WTK_MICROSOFT_VISUAL_STUDIO_2012 1700
    #define WTK_MICROSOFT_VISUAL_STUDIO_2010 1600
    #define WTK_MICROSOFT_VISUAL_STUDIO_2008 1500
    #define WTK_MICROSOFT_VISUAL_STUDIO_2005 1400
    #define WTK_MICROSOFT_VISUAL_STUDIO_2003 1310
    #define WTK_MICROSOFT_VISUAL_STUDIO_2002 1300
    #define WTK_MICROSOFT_VISUAL_C_6 1200
    #if (_MSC_VER >= MICROSOFT_VISUAL_STUDIO_2005)
      /* Only support Microsoft Visual Studio 2005 or newer. */
    #elif (_MSC_VER == MICROSOFT_VISUAL_STUDIO_2003)
      #error ("Microsoft Visual C/C++ .NET 2003 is unsupported! Please upgrade to Microsoft Visual C/C++ 2005 or newer.")
    #elif (_MSC_VER == MICROSOFT_VISUAL_STUDIO_2002)
      /* Visual Studio .NET 2002 had major bugs so annoying that Microsoft
       * provided complementary upgrades to Microsoft Visual C/C++ .NET 2003.
       */
      #error ("Microsoft Visual C/C++ .NET 2002 is unsupported! Please upgrade to Microsoft Visual C/C++ 2005 or newer.")
    #elif (_MSC_VER == WTK_MICROSOFT_VISUAL_C_6)
      /* If we did ever want to support Visual Studio 6, we should check for
       * Service Pack 6 by checking if _MSC_FULL_VER is less than 12008804.
       */
      #error ("Microsoft Visual C/C++ 6 is unsupported! Please upgrade to Microsoft Visual C/C++ 2005 or newer.")
    #else
      #error ("Your version of Microsoft Visual C/C++ is unsupported! Please upgrade to Microsoft Visual C/C++ 2005 or newer.")
    #endif
  #elif defined(__GNUC__)
    #if defined(__clang__)
      #define WTK_COMPILER WTK_COMPILER_CLANG
      #define __CLANG_VERSION__ (__clang_major__ * 10000 \
                                 + __clang_minor__ * 100 \
                                 + __clang_patchlevel__)
    #else
      /* HACK(mtwilliams): Assume we're being compiled with GCC. */
      #define WTK_COMPILER WTK_COMPILER_GCC
      #if defined(__GNUC_PATCHLEVEL__)
        #define __GNUC_VERSION__ (__GNUC__ * 10000 \
                                  + __GNUC_MINOR__ * 100 \
                                  + __GNUC_PATCHLEVEL__)
      #else
        #define __GNUC_VERSION__ (__GNUC__ * 10000 \
                                  + __GNUC_MINOR__ * 100)
      #endif
    #endif
  #else
    #error ("Unknown or unsupported compiler!")
  #endif
#endif

/**
 * \def WTK_ARCHITECTURE_X86
 * \brief Intel/AMD x86
 */
#define WTK_ARCHITECTURE_X86 1

/**
 * \def WTK_ARCHITECTURE_X86_64
 * \brief Intel/AMD x86_64
 */
#define WTK_ARCHITECTURE_X86_64 2

/**
 * \def WTK_ARCHITECTURE
 * \brief Target architecture.
 */
#if defined(DOXYGEN)
  #define WTK_ARCHITECTURE
#else
  #if defined(_M_IX86) || defined(__i386__)
    #define WTK_ARCHITECTURE WTK_ARCHITECTURE_X86
  #elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__)
    #define WTK_ARCHITECTURE WTK_ARCHITECTURE_X86_64
  #else
    #error ("Unknown or unsupported architecture!")
  #endif
#endif

#endif /* _WTK_CONFIG_H_ */


text:
/*===-- wtk/linkage.h ---------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_LINKAGE_H_
#define _WTK_LINKAGE_H_

/**
 * \def WTK_LINKAGE_INTERNAL
 * \brief Export symbols for inclusion via objects.
 */
#define WTK_LINKAGE_INTERNAL 0

/**
 * \def WTK_LINKAGE_STATIC
 * \brief Export symbols for inclusion via static library.
 */
#define WTK_LINKAGE_STATIC 1

/**
 * \def WTK_LINKAGE_DYNAMIC
 * \brief Export symbols for inclusion via dynamic library.
 */
#define WTK_LINKAGE_DYNAMIC 2

/**
 * \def WTK_LINKAGE
 * \brief Specifies how you intend to link to WTK.
 */
#ifndef WTK_LINKAGE
  #error ("Please specify how you intend on linking to WTK by defining `WTK_LINKAGE'.")
#endif

/**
 * \def WTK_PUBLIC
 * \brief Marks a symbol for public usage.
 */
#if defined(DOXYGEN)
  #define WTK_PUBLIC
#else
  #if WTK_LINKAGE == WTK_LINKAGE_STATIC
    #define WTK_PUBLIC
  #elif WTK_LINKAGE == WTK_LINKAGE_DYNAMIC
    #if defined(__WTK_IS_BEING_COMPILED__)
      #if defined(__GNUC__)
        #if __GNUC__ >= 4
          #define WTK_PUBLIC __attribute__ ((visibility ("default")))
        #else
          #define WTK_PUBLIC
        #endif
      #elif defined(__clang__)
        #define WTK_PUBLIC __attribute__ ((visibility ("default")))
      #elif defined(_MSC_VER) || defined(__CYGWIN__)
        #define WTK_PUBLIC __declspec(dllexport)
      #else
        #error ("Unknown or unsupported toolchain!")
      #endif
    #else
      #if (defined(__GNUC__) && (__GNUC__ >= 4))
        #define WTK_PUBLIC
      #elif defined(__clang__)
        #define WTK_PUBLIC
      #elif defined(_MSC_VER) || defined(__CYGWIN__)
        #define WTK_PUBLIC __declspec(dllimport)
      #else
        #error ("Unknown or unsupported toolchain!")
      #endif
    #endif
  #endif
#endif

/**
 * \def WTK_PRIVATE
 * \brief Marks a symbol for internal usage.
 */
#if defined(DOXYGEN)
  #define WTK_PRIVATE
#else
  #if WTK_LINKAGE == WTK_LINKAGE_STATIC
    #define WTK_PRIVATE
  #elif WTK_LINKAGE == WTK_LINKAGE_DYNAMIC
    #if defined(__WTK_IS_BEING_COMPILED__)
      #if defined(__GNUC__)
        #if __GNUC__ >= 4
          #define WTK_PRIVATE __attribute__ ((visibility ("hidden")))
        #else
          #define WTK_PRIVATE
        #endif
      #elif defined(__clang__)
        #define WTK_PRIVATE __attribute__ ((visibility ("hidden")))
      #elif defined(_MSC_VER) || defined(__CYGWIN__)
        #define WTK_PRIVATE
      #else
        #error ("Unknown or unsupported toolchain!")
      #endif
    #else
      #define WTK_PRIVATE
    #endif
  #endif
#endif

/**
 * \def WTK_BEGIN_EXTERN_C
 * \internal
 */

/**
 * \def WTK_END_EXTERN_C
 * \internal
 */

#if defined(DOXYGEN)
  #define WTK_BEGIN_EXTERN_C
  #define WTK_END_EXTERN_C
#else
  #if defined(__cplusplus)
    #define WTK_BEGIN_EXTERN_C extern "C" {
    #define WTK_END_EXTERN_C }
  #else
    #define WTK_BEGIN_EXTERN_C
    #define WTK_END_EXTERN_C
  #endif
#endif

#endif /* _WTK_LINKAGE_H_ */


text:
/*===-- wtk/window.h ----------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_WINDOW_H_
#define _WTK_WINDOW_H_

#include "wtk/foundation.h"

#include "wtk/handle.h"

/* REFACTOR(mtwilliams): Forward declare. */
#include "wtk/canvas.h"

WTK_BEGIN_EXTERN_C

typedef enum wtk_window_event_type {
  WTK_WINDOW_EVENT_OPENED,
  WTK_WINDOW_EVENT_CLOSED,
  WTK_WINDOW_EVENT_VISIBILITY,
  WTK_WINDOW_EVENT_MOVED,
  WTK_WINDOW_EVENT_RESIZED,
  WTK_WINDOW_EVENT_DRAW
} wtk_window_event_type_t;

typedef struct wtk_window_event {
  wtk_window_event_type_t type;

  union {
    struct {
    } opened;

    struct {
      unsigned destroying;
    } closed;

    struct {
      unsigned visible;
    } visibility;

    struct {
      wtk_canvas_t *canvas;
      wtk_rectangle_t dirty;
    } draw;
  };
} wtk_window_event_t;

typedef wtk_uint32_t (*wtk_window_event_handler_t)(wtk_handle_t handle,
                                                   const wtk_window_event_t *event,
                                                   void *context);

typedef struct wtk_window_desc {
  const char *title;

  wtk_uint32_t x;
  wtk_uint32_t y;
  wtk_uint32_t width;
  wtk_uint32_t height;

  unsigned resizeable;
  unsigned closable;

  wtk_window_event_handler_t event_handler;
  void *event_handler_context;
} wtk_window_desc_t;

extern WTK_PUBLIC
  wtk_handle_t wtk_window_open(
    const wtk_window_desc_t *desc);

extern WTK_PUBLIC
  void wtk_window_close(
    wtk_handle_t handle);

extern WTK_PUBLIC
  unsigned wtk_window_is_resizeable(
    wtk_handle_t handle);

extern WTK_PUBLIC
  unsigned wtk_window_is_closable(
    wtk_handle_t handle);

extern WTK_PUBLIC
  wtk_uintptr_t wtk_window_to_native(
    wtk_handle_t handle);

extern WTK_PUBLIC
  wtk_canvas_t *wtk_window_to_canvas(
    wtk_handle_t handle);

WTK_END_EXTERN_C

#endif /* _WTK_WINDOW_H_ */


text:
/*===-- wtk/foundation.h ------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_FOUNDATION_H_
#define _WTK_FOUNDATION_H_

#include "wtk/config.h"
#include "wtk/linkage.h"

#include "wtk/foundation/types.h"
#include "wtk/foundation/support.h"
#include "wtk/foundation/utilities.h"
#include "wtk/foundation/assert.h"
#include "wtk/foundation/memory.h"

#endif /* _WTK_FOUNDATION_H_ */


text:
/*===-- wtk/wgl.h -------------------------------------------*- mode: C -*-===*/
/*                                                                            */
/*                                     _   _                                  */
/*                               _ _ _| |_| |_                                */
/*                              | | | |  _| '_|                               */
/*                              |_____|_| |_,_|                               */
/*                                                                            */
/*       This file is distributed under the terms described in LICENSE.       */
/*                                                                            */
/*===----------------------------------------------------------------------===*/

#ifndef _WTK_WGL_H_
#define _WTK_WGL_H_

#include "wtk/foundation.h"

#if WTK_PLATFORM == WTK_PLATFORM_WINDOWS

#include <windows.h>

WTK_BEGIN_EXTERN_C

extern WTK_PRIVATE
  void wtk_wgl_init(void);

extern WTK_PRIVATE
  void wtk_wgl_shutdown(void);

extern WTK_PRIVATE
  void *wtk_wgl_get_proc_address(const char *name);

typedef struct wtk_wgl_context wtk_wgl_context_t;

typedef enum wtk_wgl_context_flags {
  /*! Request debug context and enable debugging functionality. */
  WTK_WGL_CONTEXT_DEBUG = (1 << 0)
} wtk_wgl_context_flags_t;

typedef struct wtk_wgl_context_creation_params {
  /*! Minimum required context version. */
  struct {
    wtk_uint32_t major;
    wtk_uint32_t minor;
  } version;

  /*! \copydoc wtk_wgl_context_flags_t */
  wtk_uint32_t flags;

  /*! Context to share resources with. */
  wtk_wgl_context_t *share;
} wtk_wgl_context_creation_params_t;

extern WTK_PRIVATE
  wtk_wgl_context_t *wtk_wgl_create_context(
    const wtk_wgl_context_creation_params_t *ccp);

extern WTK_PRIVATE
  void wtk_wgl_destroy_context(
    wtk_wgl_context_t *context);

typedef struct wtk_wgl_surface wtk_wgl_surface_t;

extern WTK_PRIVATE
  wtk_wgl_surface_t *wtk_wgl_create_surface(
    wtk_wgl_context_t *context,
    HWND window);

extern WTK_PRIVATE
  void wtk_wgl_destroy_surface(
    wtk_wgl_surface_t *surface);

extern WTK_PRIVATE
  void wtk_wgl_dimensions_of_surface(
    wtk_wgl_surface_t *surface,
    wtk_uint32_t *width,
    wtk_uint32_t *height);

extern WTK_PRIVATE
  void wtk_wgl_bind(
    wtk_wgl_context_t *context,
    wtk_wgl_surface_t *surface);

typedef enum wtk_wgl_present_flags {
  /*! Synchronize to vertical blanks. */
  WTK_WGL_PRESENT_SYNCHRONIZE = (1 << 0)
} wtk_wgl_present_flags_t;

extern WTK_PRIVATE
  void wtk_wgl_present(
    wtk_wgl_surface_t *surface,
    wtk_uint32_t flags);

WTK_END_EXTERN_C

#endif

#endif /* _WTK_WGL_H_ */