15db71995Sopenharmony_ci/* 25db71995Sopenharmony_ci * 35db71995Sopenharmony_ci * Copyright (c) 2018 Google Inc. 45db71995Sopenharmony_ci * 55db71995Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 65db71995Sopenharmony_ci * you may not use this file except in compliance with the License. 75db71995Sopenharmony_ci * You may obtain a copy of the License at 85db71995Sopenharmony_ci * 95db71995Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 105db71995Sopenharmony_ci * 115db71995Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 125db71995Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 135db71995Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145db71995Sopenharmony_ci * See the License for the specific language governing permissions and 155db71995Sopenharmony_ci * limitations under the License. 165db71995Sopenharmony_ci * 175db71995Sopenharmony_ci */ 185db71995Sopenharmony_ci 195db71995Sopenharmony_ci#include "dlopen_fuchsia.h" 205db71995Sopenharmony_ci 215db71995Sopenharmony_ci#include <fcntl.h> 225db71995Sopenharmony_ci#include <fuchsia/vulkan/loader/c/fidl.h> 235db71995Sopenharmony_ci#include <lib/fdio/io.h> 245db71995Sopenharmony_ci#include <lib/fdio/directory.h> 255db71995Sopenharmony_ci#include <stdio.h> 265db71995Sopenharmony_ci#include <string.h> 275db71995Sopenharmony_ci#include <threads.h> 285db71995Sopenharmony_ci#include <zircon/dlfcn.h> 295db71995Sopenharmony_ci#include <zircon/syscalls.h> 305db71995Sopenharmony_ci 315db71995Sopenharmony_cistatic char g_error[128] = {}; 325db71995Sopenharmony_ci 335db71995Sopenharmony_ciconst char *dlerror_fuchsia(void) { return g_error; } 345db71995Sopenharmony_ci 355db71995Sopenharmony_cistatic zx_handle_t vulkan_loader_svc = ZX_HANDLE_INVALID; 365db71995Sopenharmony_civoid connect_to_vulkan_loader_svc(void) { 375db71995Sopenharmony_ci zx_handle_t svc1, svc2; 385db71995Sopenharmony_ci if (zx_channel_create(0, &svc1, &svc2) != ZX_OK) return; 395db71995Sopenharmony_ci 405db71995Sopenharmony_ci if (fdio_service_connect("/svc/" fuchsia_vulkan_loader_Loader_Name, svc1) != ZX_OK) { 415db71995Sopenharmony_ci zx_handle_close(svc2); 425db71995Sopenharmony_ci return; 435db71995Sopenharmony_ci } 445db71995Sopenharmony_ci 455db71995Sopenharmony_ci vulkan_loader_svc = svc2; 465db71995Sopenharmony_ci} 475db71995Sopenharmony_ci 485db71995Sopenharmony_cistatic once_flag svc_connect_once_flag = ONCE_FLAG_INIT; 495db71995Sopenharmony_ci 505db71995Sopenharmony_civoid *dlopen_fuchsia(const char *name, int mode, bool driver) { 515db71995Sopenharmony_ci // First try to just dlopen() from our own namespace. This will succeed for 525db71995Sopenharmony_ci // any layers that are packaged with the application, but will fail for 535db71995Sopenharmony_ci // client drivers loaded from the system. 545db71995Sopenharmony_ci void *result; 555db71995Sopenharmony_ci if (!driver) { 565db71995Sopenharmony_ci result = dlopen(name, mode); 575db71995Sopenharmony_ci if (result != NULL) return result; 585db71995Sopenharmony_ci } 595db71995Sopenharmony_ci 605db71995Sopenharmony_ci // If we couldn't find the library in our own namespace, connect to the 615db71995Sopenharmony_ci // loader service to request this library. 625db71995Sopenharmony_ci call_once(&svc_connect_once_flag, connect_to_vulkan_loader_svc); 635db71995Sopenharmony_ci 645db71995Sopenharmony_ci if (vulkan_loader_svc == ZX_HANDLE_INVALID) { 655db71995Sopenharmony_ci snprintf(g_error, sizeof(g_error), "libvulkan.so:dlopen_fuchsia: no connection to loader svc\n"); 665db71995Sopenharmony_ci return NULL; 675db71995Sopenharmony_ci } 685db71995Sopenharmony_ci 695db71995Sopenharmony_ci zx_handle_t vmo = ZX_HANDLE_INVALID; 705db71995Sopenharmony_ci zx_status_t st = fuchsia_vulkan_loader_LoaderGet(vulkan_loader_svc, name, strlen(name), &vmo); 715db71995Sopenharmony_ci if (st != ZX_OK) { 725db71995Sopenharmony_ci snprintf(g_error, sizeof(g_error), "libvulkan.so:dlopen_fuchsia: Get() failed: %d\n", st); 735db71995Sopenharmony_ci return NULL; 745db71995Sopenharmony_ci } 755db71995Sopenharmony_ci 765db71995Sopenharmony_ci if (vmo == ZX_HANDLE_INVALID) { 775db71995Sopenharmony_ci snprintf(g_error, sizeof(g_error), "libvulkan.so:dlopen_fuchsia: Get() returned invalid vmo\n"); 785db71995Sopenharmony_ci return NULL; 795db71995Sopenharmony_ci } 805db71995Sopenharmony_ci 815db71995Sopenharmony_ci result = dlopen_vmo(vmo, mode); 825db71995Sopenharmony_ci zx_handle_close(vmo); 835db71995Sopenharmony_ci if (!result) { 845db71995Sopenharmony_ci snprintf(g_error, sizeof(g_error), "%s", dlerror()); 855db71995Sopenharmony_ci } 865db71995Sopenharmony_ci return result; 875db71995Sopenharmony_ci} 88