xdl_int XdevLOpenGLWGL::create(XdevLWindow* window) {

		if(window == NULL) {
			XDEVL_MODULE_ERROR("Parameter invalid.\n");
			return ERR_ERROR;
		}

		m_window = window;
		m_wnd = static_cast<HWND>(m_window->getInternal(XdevLInternalName("WIN32_HWND")));
		if ( m_wnd == NULL) {
			XDEVL_MODULE_ERROR("Get WIN32_HWND failed.\n");
			return ERR_ERROR;
		}

		if (initOpenGL() == ERR_ERROR) {
			XDEVL_MODULE_ERROR("Failed to initialize OpenGL.\n");
			return ERR_ERROR;
		}

		// Set vertical syncronisation.
		setVSync(getVSync());

		// TODO: This shouldn't be done maybe because it changes the initial state of the OpenGL context.
		glClearColor(1.0, 0.0, 0.0, 1.0);
		glClear(GL_COLOR_BUFFER_BIT);
		SwapBuffers(m_DC);

		return ERR_OK;
	}
	int XdevLOpenGLContextGLX::create(XdevLWindow* window, XdevLOpenGLContext* shareContext) {
		XDEVL_ASSERT(m_display == nullptr, "XdevLOpenGLContextGLX already created.");

		if(nullptr != shareContext) {
			m_shareContext = static_cast<XdevLOpenGLContextGLX*>(shareContext);
		}

		window->getDescriptor().registerDependency(this);

		m_display = static_cast<Display*>(window->getInternal(XdevLInternalName("X11_DISPLAY")));
		if(nullptr == m_display) {
			XDEVL_MODULE_ERROR("Could not get native X11 display information.\n");
			return RET_FAILED;
		}

		m_window = (Window)(window->getInternal(XdevLInternalName("X11_WINDOW")));
		if(None == m_window) {
			XDEVL_MODULE_ERROR("Could not get native X11 window information.\n");
			return RET_FAILED;
		}

		if(glXQueryVersion(m_display, &m_glxMajorVersion, &m_glxMinorVersion) == False) {
			XDEVL_MODULE_ERROR("glXQueryVersion failed.\n");
			return RET_FAILED;
		}

		if(initOpenGL(m_display, m_window) == RET_FAILED) {
			XDEVL_MODULE_ERROR("Failed to initialize OpenGL.\n");
			return RET_FAILED;
		}

		if(glXIsDirect(m_display, m_glxContext)) {
			XDEVL_MODULE_INFO("Direct Rendering supported.\n");

		} else {
			XDEVL_MODULE_WARNING("Direct Rendering not supported.\n");
		}

		setVSync(getVSync());

		return RET_SUCCESS;
	}
	int XdevLSwapChainVulkan::createSurface(IPXdevLWindow window) {
		Display* display = static_cast<Display*>(window->getInternal(XdevLInternalName("X11_DISPLAY")));
		if(nullptr == display) {
			XDEVL_MODULEX_ERROR(XdevLSwapChainVulkan, "Could not get native X11 display information.\n");
			return RET_FAILED;
		}

		Window x11window = (Window)(window->getInternal(XdevLInternalName("X11_WINDOW")));
		if(None == x11window) {
			XDEVL_MODULEX_ERROR(XdevLSwapChainVulkan, "Could not get native X11 window information.\n");
			return RET_FAILED;
		}

		//
		// Get the Surface extensions.
		//
		VkResult result;

#if defined(_WIN32)
		VkWin32SurfaceCreateInfoKHR surfaceCreateInfo;
		surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
		surfaceCreateInfo.hinstance = (HINSTANCE)platformHandle; // provided by the platform code
		surfaceCreateInfo.hwnd = (HWND)platformWindow;           // provided by the platform code
		result = vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &m_surface);
#elif defined(__ANDROID__)
		VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
		surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
		surfaceCreateInfo.window = window;                       // provided by the platform code
		result = vkCreateAndroidSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &m_surface);
#else
		VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {
			VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
			nullptr,
			0,
			XGetXCBConnection(display),
			(xcb_window_t)x11window
		};
		result = vkCreateXcbSurfaceKHR(m_instance, &surfaceCreateInfo, nullptr, &m_surface);
#endif
		if(result != VK_SUCCESS) {
			std::cerr << "Failed to create Vulkan surface: " << vkVkResultToString(result) << std::endl;
			return 1;
		}


		uint32_t queueCount;
		vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueCount, nullptr);

		std::vector<VkQueueFamilyProperties> queueProps(queueCount);
		vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueCount, queueProps.data());

		// Will be used to present the swap chain images to the windowing system
		std::vector<VkBool32> supportsPresent(queueCount);
		for(uint32_t i = 0; i < queueCount; i++) {
			fpGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &supportsPresent[i]);

		}



		// Search for a graphics and a present queue in the array of queue
		// families, try to find one that supports both
		uint32_t graphicsQueueNodeIndex = UINT32_MAX;
		uint32_t presentQueueNodeIndex = UINT32_MAX;
		for(uint32_t i = 0; i < queueCount; i++) {
			if((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
				if(graphicsQueueNodeIndex == UINT32_MAX) {
					graphicsQueueNodeIndex = i;
				}

				if(supportsPresent[i] == VK_TRUE) {
					graphicsQueueNodeIndex = i;
					presentQueueNodeIndex = i;
					break;
				}
			}
		}
		if(presentQueueNodeIndex == UINT32_MAX) {
			// If there's no queue that supports both present and graphics
			// try to find a separate present queue
			for(uint32_t i = 0; i < queueCount; ++i) {
				if(supportsPresent[i] == VK_TRUE) {
					presentQueueNodeIndex = i;
					break;
				}
			}
		}

		// Exit if either a graphics or a presenting queue hasn't been found
		if(graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX) {
			return 1;
		}

		// todo : Add support for separate graphics and presenting queue
		if(graphicsQueueNodeIndex != presentQueueNodeIndex) {
			return 1;
		}

		m_queueNodeIndex = graphicsQueueNodeIndex;

		// Get list of supported surface formats
		uint32_t formatCount;
		result = vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr);
		if(VK_SUCCESS != result) {
			std::cerr << "vkGetPhysicalDeviceSurfaceFormatsKHR failed: " << vkVkResultToString(result) << std::endl;
			return 1;
		}
		assert(formatCount > 0);

		std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
		result = vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, surfaceFormats.data());
		assert(!result);



		// If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
		// there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
		if((formatCount == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED)) {
			m_colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
		} else {
			// Always select the first available color format
			// If you need a specific format (e.g. SRGB) you'd need to
			// iterate over the list of available surface format and
			// check for it's presence
			m_colorFormat = surfaceFormats[0].format;
		}

		m_colorSpace = surfaceFormats[0].colorSpace;

		return 0;
	}