GFXMeshBuffer gfx_mesh_add_buffer( GFXMesh* mesh, size_t size, const void* data) { GFX_Mesh* internal = (GFX_Mesh*)mesh; /* Insert new vector element */ GFXSharedBuffer* it = gfx_vector_insert( &internal->buffers, NULL, internal->buffers.end ); if(it == internal->buffers.end) return 0; /* Create new shared buffer */ /* Align with largest integer so index offset can be aligned */ GFXDataType type; type.unpacked = GFX_LARGE_INTEGER; if(!gfx_shared_buffer_init_align(it, size, data, type)) { gfx_vector_erase(&internal->buffers, it); return 0; } /* Return ID */ return gfx_vector_get_size(&internal->buffers); }
GFX_Win32_Window* _gfx_win32_window_dummy_create(void) { /* Create a dummy window */ GFX_Win32_Window window; window.monitor = NULL; window.context = NULL; window.flags = GFX_WIN32_HIDDEN; window.handle = CreateWindow( GFX_WIN32_WINDOW_CLASS_DUMMY, L"", 0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL ); if(window.handle) { /* Add window to vector */ GFXVectorIterator it = gfx_vector_insert( &_gfx_win32.windows, &window, _gfx_win32.windows.end ); if(it != _gfx_win32.windows.end) { /* Set pixel format */ GFXColorDepth depth; depth.redBits = 0; depth.greenBits = 0; depth.blueBits = 0; _gfx_win32_set_pixel_format(window.handle, &depth, 0); return it; } /* Nevermind */ DestroyWindow(window.handle); } return NULL; }
static size_t _gfx_x11_init_modes( Screen* scr, XRRScreenResources* res) { /* Split depth */ GFXColorDepth depth; _gfx_split_depth( XDefaultDepthOfScreen(scr), &depth.redBits, &depth.greenBits, &depth.blueBits ); /* Reserve space for all modes */ size_t first = gfx_vector_get_size(&_gfx_x11.modes); gfx_vector_reserve(&_gfx_x11.modes, first + res->nmode); unsigned int i; for(i = 0; i < res->nmode; ++i) { /* Skip refresh rate of zero */ unsigned int refresh = 0; if(res->modes[i].hTotal && res->modes[i].vTotal) { refresh = (unsigned int)lround((double)res->modes[i].dotClock / ((double)res->modes[i].hTotal * (double)res->modes[i].vTotal)); } if(refresh) { /* Create new mode */ GFX_X11_Mode mode; mode.id = res->modes[i].id; mode.mode.width = res->modes[i].width; mode.mode.height = res->modes[i].height; mode.mode.depth = depth; mode.mode.refresh = refresh; gfx_vector_insert(&_gfx_x11.modes, &mode, _gfx_x11.modes.end); } } return first; }
static GFXMeshLayout _gfx_mesh_insert_layout( GFX_Mesh* mesh, GFXVertexLayout* layout) { GFXVectorIterator it = gfx_vector_insert( &mesh->layouts, &layout, mesh->layouts.end ); if(it == mesh->layouts.end) { /* Free on failure */ gfx_vertex_layout_free(layout); return 0; } /* Return the ID */ return gfx_vector_get_size(&mesh->layouts); }
static int _gfx_thread_pool_push( GFX_Pool* pool, GFX_Task task) { /* Insert the new element */ size_t elem = gfx_vector_get_size(&pool->tasks); GFX_Task* et = gfx_vector_insert( &pool->tasks, &task, pool->tasks.end ); if(et == pool->tasks.end) return 0; /* Correct heap again */ while(elem > 0) { /* Get parent and compare */ size_t parent = (elem - 1) >> 1; GFX_Task* pt = gfx_vector_at(&pool->tasks, parent); if(pt->priority <= et->priority) break; /* Swap */ task = *pt; *pt = *et; *et = task; elem = parent; } return 1; }
GFX_PlatformWindow _gfx_platform_window_create( const GFX_PlatformAttributes* attributes) { /* Setup the x11 window */ GFX_X11_Window window; window.monitor = attributes->monitor; window.context = NULL; window.flags = 0; window.flags |= attributes->flags & GFX_WINDOW_RESIZABLE ? GFX_X11_RESIZABLE : 0; window.flags |= attributes->flags & GFX_WINDOW_HIDDEN ? GFX_X11_HIDDEN : 0; /* Get display mode & position */ GFXDisplayMode mode; int x = window.monitor->x; int y = window.monitor->y; if(attributes->flags & GFX_WINDOW_FULLSCREEN) { window.flags |= GFX_X11_FULLSCREEN; GFX_X11_Mode* it = gfx_vector_at( &_gfx_x11.modes, window.monitor->modes[attributes->mode] ); window.mode = it->id; mode = it->mode; } else { mode.width = attributes->w; mode.height = attributes->h; mode.depth = *attributes->depth; x += attributes->x; y += attributes->y; } /* Get FB Config */ GLXFBConfig* config = _gfx_x11_get_config( window.monitor->screen, &mode.depth, attributes->flags & GFX_WINDOW_DOUBLE_BUFFER ); if(!config) return NULL; /* Get visual from config */ XVisualInfo* visual = glXGetVisualFromFBConfig( _gfx_x11.display, *config ); window.config = *config; XFree(config); /* Create the window attributes */ unsigned long mask = CWColormap | CWEventMask; XSetWindowAttributes attr; if( attributes->flags & GFX_WINDOW_BORDERLESS || attributes->flags & GFX_WINDOW_FULLSCREEN) { /* Borderless window */ mask |= CWBorderPixel; attr.border_pixel = 0; } /* Event mask & Color map */ Window root = XRootWindowOfScreen(window.monitor->screen); attr.event_mask = KeyPressMask | KeyReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | FocusChangeMask; attr.colormap = XCreateColormap( _gfx_x11.display, root, visual->visual, AllocNone ); /* Create the actual window */ window.handle = XCreateWindow( _gfx_x11.display, root, x, y, mode.width, mode.height, 0, visual->depth, InputOutput, visual->visual, mask, &attr ); XFree(visual); if(window.handle) { /* Get properties to check for events */ XWindowAttributes get; get.x = 0; get.y = 0; get.width = 0; get.height = 0; XGetWindowAttributes(_gfx_x11.display, window.handle, &get); window.x = get.x; window.y = get.y; window.width = get.width; window.height = get.height; /* Delete protocol & name */ XSetWMProtocols( _gfx_x11.display, window.handle, &_gfx_x11.WM_DELETE_WINDOW, 1); XStoreName( _gfx_x11.display, window.handle, attributes->name); /* Disable decorations */ if(mask & CWBorderPixel) { unsigned long hints[5]; hints[0] = MWM_HINTS_DECORATIONS; hints[2] = 0; XChangeProperty( _gfx_x11.display, window.handle, _gfx_x11.MOTIF_WM_HINTS, _gfx_x11.MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char*)hints, 5); } /* Bypass compositor */ if(attributes->flags & GFX_WINDOW_FULLSCREEN) { unsigned long bypass = 1; XChangeProperty( _gfx_x11.display, window.handle, _gfx_x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&bypass, 1 ); } /* Set size hints */ if(!(attributes->flags & GFX_WINDOW_RESIZABLE)) { XSizeHints* hints = XAllocSizeHints(); hints->flags = PMinSize | PMaxSize; hints->min_width = mode.width; hints->max_width = mode.width; hints->min_height = mode.height; hints->max_height = mode.height; XSetWMNormalHints(_gfx_x11.display, window.handle, hints); XFree(hints); } /* Add window to vector */ GFXVectorIterator it = gfx_vector_insert( &_gfx_x11.windows, &window, _gfx_x11.windows.end ); if(it != _gfx_x11.windows.end) { /* Make it visible */ /* Triggers FocusIn event for fullscreen */ if(!(attributes->flags & GFX_WINDOW_HIDDEN)) XMapWindow(_gfx_x11.display, window.handle); return GFX_UINT_TO_VOID(window.handle); } XDestroyWindow(_gfx_x11.display, window.handle); } XFreeColormap(_gfx_x11.display, attr.colormap); return NULL; }
GFX_PlatformWindow _gfx_platform_window_create( const GFX_PlatformAttributes* attributes) { /* Setup the win32 window */ GFX_Win32_Window window; window.monitor = attributes->monitor; window.context = NULL; window.flags = 0; window.flags |= attributes->flags & GFX_WINDOW_RESIZABLE ? GFX_WIN32_RESIZABLE : 0; window.flags |= attributes->flags & GFX_WINDOW_HIDDEN ? GFX_WIN32_HIDDEN : 0; /* Display mode, style and window rectangle */ DWORD styleEx = WS_EX_APPWINDOW; DWORD style = (!(attributes->flags & GFX_WINDOW_HIDDEN) ? WS_VISIBLE : 0); GFXColorDepth depth; RECT rect; rect.left = window.monitor->x; rect.top = window.monitor->y; if(attributes->flags & GFX_WINDOW_FULLSCREEN) { /* Display mode */ window.flags |= GFX_WIN32_FULLSCREEN; window.mode = gfx_vector_at( &_gfx_win32.modes, window.monitor->modes + attributes->mode); _gfx_split_depth( window.mode->dmBitsPerPel, &depth.redBits, &depth.greenBits, &depth.blueBits); /* Style and rectangle */ rect.right = window.mode->dmPelsWidth; rect.bottom = window.mode->dmPelsHeight; styleEx |= WS_EX_TOPMOST; style |= WS_POPUP; } else { /* Color depth and rectangle */ depth = *attributes->depth; rect.right = attributes->w; rect.bottom = attributes->h; rect.left += attributes->x; rect.top += attributes->y; /* Style */ style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS; if(!(attributes->flags & GFX_WINDOW_BORDERLESS)) { /* With a border */ styleEx |= WS_EX_WINDOWEDGE; style |= WS_CAPTION | WS_MINIMIZEBOX | WS_OVERLAPPED | WS_SYSMENU; /* With size options */ if(attributes->flags & GFX_WINDOW_RESIZABLE) style |= WS_MAXIMIZEBOX | WS_SIZEBOX; } else { /* Borderless */ styleEx |= WS_EX_TOPMOST; style |= WS_POPUP; } } rect.right += rect.left; rect.bottom += rect.top; /* Make sure the client area is the specified size */ AdjustWindowRectEx(&rect, style, FALSE, styleEx); /* Convert name to UTF-16 */ WCHAR* name = _gfx_win32_utf8_to_utf16(attributes->name); /* Create the actual window */ window.handle = CreateWindowEx( styleEx, GFX_WIN32_WINDOW_CLASS, name, style, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, GetModuleHandle(NULL), NULL ); free(name); if(window.handle) { /* Add window to vector */ GFXVectorIterator it = gfx_vector_insert( &_gfx_win32.windows, &window, _gfx_win32.windows.end ); if(it != _gfx_win32.windows.end) { /* Set pixel format */ _gfx_win32_set_pixel_format( window.handle, &depth, attributes->flags & GFX_WINDOW_DOUBLE_BUFFER ); /* Start tracking the mouse */ _gfx_win32_track_mouse(window.handle); /* Enter fullscreen */ if( (attributes->flags & GFX_WINDOW_FULLSCREEN) && !(attributes->flags & GFX_WINDOW_HIDDEN)) { _gfx_win32_enter_fullscreen(window.monitor, window.mode); } return window.handle; } DestroyWindow(window.handle); } return NULL; }
static int _gfx_x11_init_monitors( int major, int minor) { /* Iterate over all screens */ Screen* def = XDefaultScreenOfDisplay(_gfx_x11.display); unsigned int count = XScreenCount(_gfx_x11.display); while(count--) { /* Get screen resources */ Screen* scr = XScreenOfDisplay(_gfx_x11.display, count); Window root = XRootWindowOfScreen(scr); XRRScreenResources* res = XRRGetScreenResources(_gfx_x11.display, root); RROutput prim = res->outputs[0]; /* Get primary if RandR 1.3 is supported */ if(major > 1 || (major == 1 && minor > 2)) prim = XRRGetOutputPrimary(_gfx_x11.display, root); /* Insert the screen's display modes */ size_t first = _gfx_x11_init_modes(scr, res); /* Iterate through outputs */ unsigned int i; for(i = 0; i < res->noutput; ++i) { /* Validate output */ XRROutputInfo* out = XRRGetOutputInfo(_gfx_x11.display, res, res->outputs[i]); if(out->connection != RR_Connected) { XRRFreeOutputInfo(out); continue; } /* Create new monitor */ XRRCrtcInfo* crtc = XRRGetCrtcInfo(_gfx_x11.display, res, out->crtc); int rot = crtc->rotation & (RR_Rotate_90 | RR_Rotate_270); GFX_X11_Monitor mon = { .screen = scr, .crtc = out->crtc, .mode = crtc->mode, .numModes = 0, .modes = malloc(sizeof(size_t) * out->nmode), .x = crtc->x, .y = crtc->y, .width = rot ? crtc->height : crtc->width, .height = rot ? crtc->width : crtc->height }; /* Retrieve output modes */ unsigned int j; if(mon.modes) for(j = 0; j < out->nmode; ++j) { GFX_X11_Mode* mode; for( mode = gfx_vector_at(&_gfx_x11.modes, first); mode != _gfx_x11.modes.end; mode = gfx_vector_next(&_gfx_x11.modes, mode)) { /* Also check if resolution isn't too big */ if( mode->id == out->modes[j] && mode->mode.width <= crtc->width && mode->mode.height <= crtc->height) { mon.modes[mon.numModes++] = gfx_vector_get_index( &_gfx_x11.modes, mode ); break; } } } /* Insert at beginning if primary */ GFXVectorIterator monPos = scr == def && res->outputs[i] == prim ? _gfx_x11.monitors.begin : _gfx_x11.monitors.end; monPos = gfx_vector_insert(&_gfx_x11.monitors, &mon, monPos); if(monPos == _gfx_x11.monitors.end) free(mon.modes); XRRFreeCrtcInfo(crtc); XRRFreeOutputInfo(out); } XRRFreeScreenResources(res); } /* Need at least one monitor */ return _gfx_x11.monitors.begin != _gfx_x11.monitors.end; } /******************************************************/ static GFXKey _gfx_x11_get_key( KeySym symbol) { /* Unicode numbers */ if(symbol >= XK_0 && symbol <= XK_9) return (GFXKey)(symbol - XK_0 + GFX_KEY_0); /* Keypad numbers */ if(symbol >= XK_KP_0 && symbol <= XK_KP_9) return (GFXKey)(symbol - XK_KP_0 + GFX_KEY_KP_0); /* Unicode capitals */ if(symbol >= XK_A && symbol <= XK_Z) return (GFXKey)(symbol - XK_A + GFX_KEY_A); /* Unicode lowercase */ if(symbol >= XK_a && symbol <= XK_z) return (GFXKey)(symbol - XK_a + GFX_KEY_A); /* Function keys */ if(symbol >= XK_F1 && symbol <= XK_F24) return (GFXKey)(symbol - XK_F1 + GFX_KEY_F1); /* Non-unicode */ switch(symbol) { case XK_VoidSymbol : return GFX_KEY_UNKNOWN; case XK_BackSpace : return GFX_KEY_BACKSPACE; case XK_Tab : return GFX_KEY_TAB; case XK_KP_Tab : return GFX_KEY_TAB; case XK_Clear : return GFX_KEY_CLEAR; case XK_Return : return GFX_KEY_RETURN; case XK_Pause : return GFX_KEY_PAUSE; case XK_Scroll_Lock : return GFX_KEY_SCROLL_LOCK; case XK_Escape : return GFX_KEY_ESCAPE; case XK_Delete : return GFX_KEY_DELETE; case XK_KP_Delete : return GFX_KEY_DELETE; case XK_Home : return GFX_KEY_HOME; case XK_KP_Home : return GFX_KEY_HOME; case XK_Left : return GFX_KEY_LEFT; case XK_KP_Left : return GFX_KEY_LEFT; case XK_Up : return GFX_KEY_UP; case XK_KP_Up : return GFX_KEY_UP; case XK_Right : return GFX_KEY_RIGHT; case XK_KP_Right : return GFX_KEY_RIGHT; case XK_Down : return GFX_KEY_DOWN; case XK_KP_Down : return GFX_KEY_DOWN; case XK_Page_Down : return GFX_KEY_PAGE_DOWN; case XK_KP_Page_Down : return GFX_KEY_PAGE_DOWN; case XK_Page_Up : return GFX_KEY_PAGE_UP; case XK_KP_Page_Up : return GFX_KEY_PAGE_UP; case XK_End : return GFX_KEY_END; case XK_KP_End : return GFX_KEY_END; case XK_Select : return GFX_KEY_SELECT; case XK_Print : return GFX_KEY_PRINT; case XK_Execute : return GFX_KEY_EXECUTE; case XK_Insert : return GFX_KEY_INSERT; case XK_KP_Insert : return GFX_KEY_INSERT; case XK_Menu : return GFX_KEY_MENU; case XK_Cancel : return GFX_KEY_CANCEL; case XK_Help : return GFX_KEY_HELP; case XK_Num_Lock : return GFX_KEY_NUM_LOCK; case XK_KP_Space : return GFX_KEY_SPACE; case XK_space : return GFX_KEY_SPACE; case XK_KP_Enter : return GFX_KEY_KP_RETURN; case XK_KP_Multiply : return GFX_KEY_KP_MULTIPLY; case XK_KP_Add : return GFX_KEY_KP_ADD; case XK_KP_Separator : return GFX_KEY_KP_SEPARATOR; case XK_KP_Subtract : return GFX_KEY_KP_SUBTRACT; case XK_KP_Decimal : return GFX_KEY_KP_DECIMAL; case XK_KP_Divide : return GFX_KEY_KP_DIVIDE; case XK_Shift_L : return GFX_KEY_SHIFT_LEFT; case XK_Shift_R : return GFX_KEY_SHIFT_RIGHT; case XK_Control_L : return GFX_KEY_CONTROL_LEFT; case XK_Control_R : return GFX_KEY_CONTROL_RIGHT; case XK_Alt_L : return GFX_KEY_ALT_LEFT; case XK_Alt_R : return GFX_KEY_ALT_RIGHT; case XK_Super_L : return GFX_KEY_SUPER_LEFT; case XK_Super_R : return GFX_KEY_SUPER_RIGHT; } return GFX_KEY_UNKNOWN; } /******************************************************/ static void _gfx_x11_create_key_table(void) { /* Get permitted keycodes and their symbols */ int minKey, maxKey; XDisplayKeycodes(_gfx_x11.display, &minKey, &maxKey); maxKey = maxKey > GFX_X11_MAX_KEYCODE ? GFX_X11_MAX_KEYCODE : maxKey; int numKeys = maxKey - minKey + 1; int symbolsPerKey; KeySym* symbols = XGetKeyboardMapping( _gfx_x11.display, minKey, numKeys, &symbolsPerKey ); /* Use the first symbol of all keycodes */ size_t i; for(i = minKey; i <= maxKey; ++i) _gfx_x11.keys[i] = _gfx_x11_get_key( symbols[(i - minKey) * symbolsPerKey]); XFree(symbols); }
int gfx_lod_map_add( GFXLodMap* map, unsigned int level, void* data) { GFX_LodMap* internal = (GFX_LodMap*)map; /* Overflow */ size_t size = gfx_vector_get_size(&internal->data); if(level > map->levels || size == UINT_MAX) return 0; /* Get level iterator */ GFXVectorIterator levIt; if(level == map->levels) { /* Insert the level if it doesn't exist yet */ unsigned int upper = size; levIt = gfx_vector_insert( &internal->levels, &upper, internal->levels.end ); if(levIt == internal->levels.end) return 0; ++map->levels; } else { /* Check single data flag */ if(map->flags & GFX_LOD_SINGLE_DATA) return 0; levIt = gfx_vector_at(&internal->levels, level); } /* Get boundaries */ unsigned int begin; unsigned int end; _gfx_lod_map_get_boundaries( internal, levIt, &begin, &end ); /* Insert the data */ GFXVectorIterator it = gfx_vector_insert_at( &internal->data, data, end ); if(it == internal->data.end) { if(begin == end) { gfx_vector_erase(&internal->levels, levIt); --map->levels; } return 0; } /* Increase upper bounds */ while(levIt != internal->levels.end) { ++(*(unsigned int*)levIt); levIt = gfx_vector_next(&internal->levels, levIt); } return 1; }