void gfx_mesh_set_index_buffer( const GFXMesh* mesh, GFXMeshLayout layout, GFXMeshBuffer buffer, size_t offset) { GFX_Mesh* internal = (GFX_Mesh*)mesh; GFXVertexLayout* lay = _gfx_mesh_get_layout(internal, layout - 1); /* Pass buffer to vertex layout */ GFXSharedBuffer* buff = (GFXSharedBuffer*)gfx_vector_at( &internal->buffers, buffer - 1); gfx_vertex_layout_set_shared_index_buffer( lay, buff, offset); }
static unsigned int _gfx_lod_map_find_data( const GFX_LodMap* map, unsigned int begin, unsigned int end, const void* data, GFXVectorIterator* found) { /* Find the data and count */ GFXVectorIterator it = gfx_vector_at(&map->data, begin); while(begin != end) { if(!memcmp(it, data, map->map.compSize)) break; ++begin; it = gfx_vector_next(&map->data, it); } *found = it; return begin; }
unsigned int gfx_lod_map_has( const GFXLodMap* map, unsigned int level, const void* data) { if(level >= map->levels) return 0; const GFX_LodMap* internal = (const GFX_LodMap*)map; GFXVectorIterator it = gfx_vector_at( &internal->levels, level); /* Get boundaries */ unsigned int begin; unsigned int end; _gfx_lod_map_get_boundaries( internal, it, &begin, &end ); /* Find all instances */ unsigned int count; for(count = 0; begin != end; ++count) { begin = _gfx_lod_map_find_data( internal, begin, end, data, &it ); } return count; }
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; }