SPEC:https://www.khronos.org/registry/EGL/specs/eglspec.1.5.pdfhttps://www.khronos.org/registry/EGL/specs/eglspec.1.5.pdf

一共45条:

eglGetDisplay

/*** This is typically the first EGL function that an application calls.* It associates a private _EGLDisplay object to the native display.*/
如注释,这是第一个被调用的egl函数;返回一个_EGLDisplay 指针dispEGLDisplay EGLAPIENTRY
eglGetDisplay(EGLNativeDisplayType nativeDisplay)
//这个nativeDisplay,在wayland client就是wl_display,而在weston(server)则是gbm_device
{...plat = _eglGetNativePlatform(native_display_ptr); //native_display_ptr是nativeDisplay指针。通过传入的nativeDisplay的指针,再判断了env的native环境以后,返回egl_platforms_EGLPlatformType detected_platform = _eglGetNativePlatformFromEnv();//通过环境变量getenv(EGL_PLATFORM)和getenv(EGL_DISPLAY)确认 _EGLPlatformType;detected_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);//如果没有搜索到,则再进行如下判断,也就是通过传过来的wl_display进行判断还没有的话,就会返回失败。disp->Platform会返回_EGL_PLATFORM_WAYLAND或者_EGL_PLATFORM_DRM//所以最终在我们的wayland/weston下,client会返回_EGL_PLATFORM_WAYLAND而server会返回_EGL_PLATFORM_DRM* Find the display corresponding to the specified native display, or create a new one.这里比较严苛,要保证attrib_list完全一样,才会返回一个已经存在的disp,否则都按新的创建!第一个plat是上一个函数得到的,第二个是wl_display指针,第三个attrib_list为NULLdisp = _eglFindDisplay(plat, native_display_ptr, NULL);我们这最终创建一个新的_EGLDisplay,它的Platform指向plat,它的PlatformDisplay指向wl_display或者gbm device,为它申请attrib_list大小的Options.Attribs参数;最后加到这个_eglGlobal.DisplayList里面 /* add to the display list */disp->Next = _eglGlobal.DisplayList;_eglGlobal.DisplayList = disp;return _eglGetDisplayHandle(disp);  实际实现如下,返回disp地址return (EGLDisplay) ((disp) ? disp : EGL_NO_DISPLAY);
}我们这最终创建一个新的_EGLDisplay,
它的Platform指向plat,client是_EGL_PLATFORM_WAYLAND而server是_EGL_PLATFORM_DRM,
它的PlatformDisplay指向wl_display或者gbm device,
为它申请attrib_list大小的Options.Attribs参数;
最后加到这个_eglGlobal.DisplayList里面 static const struct {_EGLPlatformType platform;const char *name;
} egl_platforms[] = {{ _EGL_PLATFORM_X11, "x11" },{ _EGL_PLATFORM_XCB, "xcb" },{ _EGL_PLATFORM_WAYLAND, "wayland" },{ _EGL_PLATFORM_DRM, "drm" },{ _EGL_PLATFORM_ANDROID, "android" },{ _EGL_PLATFORM_HAIKU, "haiku" },{ _EGL_PLATFORM_SURFACELESS, "surfaceless" },{ _EGL_PLATFORM_DEVICE, "device" },
};

总体上看很简单,通过上层传递的wl_display或gbm_device这种 native window,来创建对应的_EGLDisplay对象,通过Platform和PlatformDisplay指定native和本地type。

eglInitialize

/*** This is typically the second EGL function that an application calls.* Here we load/initialize the actual hardware driver.*/初始化一个EGL display connection,如注释,是eglgetdisplay之后紧接着调用的函数。并且是真正初始化硬件驱动的部分,会把整个链路串起来,最终到winsys。
EGLBoolean EGLAPIENTRY
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
函数本身会返回对应的EGL的版本号,传给major和minor
{_EGLDisplay *disp = _eglLockDisplay(dpy);
...disp->Options.ForceSoftware =env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);    //先确认下是否是做软件渲染。
..._eglDriver.Initialize(disp) //以硬件渲染的选项做初始化,如果初始化失败了会以软件渲染的方式做初始化。需要明确的是,一个_EGLDisplay只会有一个dri2_egl_displaydri2_initialize(disp); //创建的就是dir2_egl_display,不同平台有差异,看后续代码块dri_initialize_wayland 或者 dri_initialize_drm,筛选条件就是getdisplay里面决定的Platform类型strcut dri2_egl_display *dri2_dpy = dri2_egl_display(disp);dri2_dpy->ref_count++;disp->Initialized = EGL_TRUE;disp->Driver = &_eglDriver;  //设置_EGLDisplay的_EGLDriver,eglapi.c文件的第一层钩子函数。
..._eglComputeVersion(disp);   //根据_egl_extensions 判断egl版本,分别是14、15、16_eglCreateExtensionsString(disp);  //如果支持这些extension,把extensions 以字符串送到_EGLDisplay->ExtensionsString里面_eglCreateAPIsString(disp);  //根据disp->ClientAPIs设置disp->ClientAPIsString,可以是OpenGL或者Opengles或者OpenVG}_eglDirver实现钩子::
const _EGLDriver _eglDriver = {.Initialize = dri2_initialize,.Terminate = dri2_terminate,.CreateContext = dri2_create_context,.DestroyContext = dri2_destroy_context,.MakeCurrent = dri2_make_current,.CreateWindowSurface = dri2_create_window_surface,.CreatePixmapSurface = dri2_create_pixmap_surface,.CreatePbufferSurface = dri2_create_pbuffer_surface,.DestroySurface = dri2_destroy_surface,.GetProcAddress = dri2_get_proc_address,.WaitClient = dri2_wait_client,.WaitNative = dri2_wait_native,.BindTexImage = dri2_bind_tex_image,.ReleaseTexImage = dri2_release_tex_image,.SwapInterval = dri2_swap_interval,.SwapBuffers = dri2_swap_buffers,.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage,.SwapBuffersRegionNOK = dri2_swap_buffers_region,.SetDamageRegion = dri2_set_damage_region,.PostSubBufferNV = dri2_post_sub_buffer,.CopyBuffers = dri2_copy_buffers,.QueryBufferAge = dri2_query_buffer_age,.CreateImageKHR = dri2_create_image,.DestroyImageKHR = dri2_destroy_image_khr,.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image,.QuerySurface = dri2_query_surface,.QueryDriverName = dri2_query_driver_name,.QueryDriverConfig = dri2_query_driver_config,
#ifdef HAVE_LIBDRM.CreateDRMImageMESA = dri2_create_drm_image_mesa,.ExportDRMImageMESA = dri2_export_drm_image_mesa,.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa,.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa,.QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats,.QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers,
#endif
#ifdef HAVE_WAYLAND_PLATFORM.BindWaylandDisplayWL = dri2_bind_wayland_display_wl,.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl,.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl,
#endif.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium,.CreateSyncKHR = dri2_create_sync,.ClientWaitSyncKHR = dri2_client_wait_sync,.SignalSyncKHR = dri2_signal_sync,.WaitSyncKHR = dri2_server_wait_sync,.DestroySyncKHR = dri2_destroy_sync,.GLInteropQueryDeviceInfo = dri2_interop_query_device_info,.GLInteropExportObject = dri2_interop_export_object,.DupNativeFenceFDANDROID = dri2_dup_native_fence_fd,.SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs,
};

dri_initialize_drm::Platform_drm.c

EGLBoolean
dri2_initialize_drm(_EGLDisplay *disp)
{_EGLDevice *dev;struct dri2_egl_display *dri2_dpy; //此子非常重要struct gbm_device *gbm;
...gbm = disp->PlatformDisplay;  //也就是wl_display 或者gbm_device,当然,因为我们这边是调用的dri2_initialize_drm, disp->PlatformDisplay一定是上层创建的gbm_device因为是第一次创建,还没有gbm对象,会调用如下:snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0); //也就是/dev/dri/card%ddri2_dpy->fd = loader_open_device(buf);  //open cardX,拿到fd; dri2_dpy就是dri2_egl_display对象指针gbm = gbm_create_device(dri2_dpy->fd);   //创建gbm device,用于通过cardX申请buffer...具体太复杂,看下段...具体太复杂,看下段...具体太复杂,看下段return gbm;如果不是第一次调用,gbm已经有了的情况下:if(gbm) dri2_dpy->fd = gbm->fd; //如果gbm已经有了,直接通过gbm获取cardX的fddri2_dpy->gbm_dri = gbm; //不管之前有没有gbm对象,此时已经有了,把gbm赋给dri2_dpy的gbm_dri这里需要明确,gbm_dri_device和gbm_device结构体是一致的。如果backend不是drm,这里会直接goto cleanup,也就是说,gbm_dri_backend必须是支持drm的,
这个设置是在dri_device_create里面赋值dev = _eglAddDevice(dri2_dpy->fd, dri2_dpy->gbm_dr->software);//通过给定的fd,通过drmGetDevice2把对应device放到 对应的_EGLDevice表里面。就在下面的dev参数内drmDevicePtr device;drmGetDevice2(fd, 0 &device);//Get information about the opened drm device_eglAddDRMDevice(device, &dev);_EGLDevice *dev;dev = _eglGlobal.DeviceList; //塞到这个DeviceList里面。return dev;
...disp->Device = dev;
...dri2_load_driver / dri2_load_driver_dri3 //区别就是看是对应的drm节点是否为render_node,如果render_node则dri3,否则dri2dri2_load_drvier_common(disp, dri2_driver_extensions/dri3_driver_extensions);__DRIextension **extensions = dri2_open_driver(disp);return loader_open_driver(driver_name, driver, path); //通过driver name 打开对应的 dri 驱动。如果是virtio-gpu就是dlopen(virtio_gpu_dri.so),返回的是dlsym的值。即extensionsdri2_bind_extensions(dri2_dpy, driver_extensions, extensions, false);//加载对应的virtio_gpu_dri.so中的能力。判断so是否支持对应的driver_extensions,支持则对应挂钩dri2_bind_extensions(dri2_dpy, optional_drvier_extensions, extensions, true);//判断dri.so中得手支持对应的optinal_driver_extensions中的能力。支持则对应挂钩。
...给dri2_dpy赋值
...一大段的钩子函数挂钩,给dri2_dpy->gbm_dri函数挂钩dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;dri2_dpy->gbm_dri->validate_image = dri2_validate_egl_image;dri2_dpy->gbm_dri->lookup_image_validated = dri2_lookup_egl_image_validated;dri2_dpy->gbm_dri->lookup_user_data = disp;dri2_dpy->gbm_dri->get_buffers = dri2_drm_get_buffers;dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer;dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format;dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers;dri2_dpy->gbm_dri->swrast_put_image2 = swrast_put_image2;dri2_dpy->gbm_dri->swrast_get_image = swrast_get_image;dri2_dpy->gbm_dri->base.v0.surface_lock_front_buffer = lock_front_buffer;dri2_dpy->gbm_dri->base.v0.surface_release_buffer = release_buffer;dri2_dpy->gbm_dri->base.v0.surface_has_free_buffers = has_free_buffers;
...dri2_setup_extensions(disp);//bind mandatory_core_extensions和optinal_core_extensionsdri2_setup_screen(disp);//比较简单,主要是把disp->Extensions相关属性如果支持置为 true;disp->Extensions.xxxx = EGL_TRUE;drm_add_configs_for_visuals(disp)
...dri2_set_WL_bind_wayland_display(disp); //主要是如果是Wayland平台,需要设置disp->Extensions.WL_bind_wayland_display = EGL_TRUE;dri2_dpy->vtbl = &dri2_drm_display_vtbl;return true;
}#################dri2和dri3的extensions有点不一样static const struct dri2_extension_match dri3_driver_extensions[] = {{ __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },{ __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) },{ NULL, 0, 0 }
};static const struct dri2_extension_match dri2_driver_extensions[] = {{ __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },{ __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },{ NULL, 0, 0 }
};#################
dri_device_create
主要填充gbm_dri_device 结构体struct gbm_dri_device *dri;dri->base.fd = fd;dri->base.bo_create = gbm_dri_bo_create;dri->base.bo_import = gbm_dri_bo_import;dri->base.bo_map = gbm_dri_bo_map;dri->base.bo_unmap = gbm_dri_bo_unmap;dri->base.is_format_supported = gbm_dri_is_format_supported;dri->base.get_format_modifier_plane_count =gbm_dri_get_format_modifier_plane_count;dri->base.bo_write = gbm_dri_bo_write;dri->base.bo_get_fd = gbm_dri_bo_get_fd;dri->base.bo_get_planes = gbm_dri_bo_get_planes;dri->base.bo_get_handle = gbm_dri_bo_get_handle_for_plane;dri->base.bo_get_plane_fd = gbm_dri_bo_get_plane_fd;dri->base.bo_get_stride = gbm_dri_bo_get_stride;dri->base.bo_get_offset = gbm_dri_bo_get_offset;dri->base.bo_get_modifier = gbm_dri_bo_get_modifier;dri->base.bo_destroy = gbm_dri_bo_destroy;dri->base.destroy = dri_destroy;dri->base.surface_create = gbm_dri_surface_create;dri->base.surface_destroy = gbm_dri_surface_destroy;dri->base.name = "drm";dri->visual_table = gbm_dri_visuals_table;dri->num_visuals = ARRAY_SIZE(gbm_dri_visuals_table);mtx_init(&dri->mutex, mtx_plain);force_sw = env_var_as_boolean("GBM_ALWAYS_SOFTWARE", false);if (!force_sw) {ret = dri_screen_create(dri);if (ret)ret = dri_screen_create_sw(dri);} else {ret = dri_screen_create_sw(dri);}################ vtbl 实现
static const struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {.authenticate = dri2_drm_authenticate,.create_window_surface = dri2_drm_create_window_surface,.create_pixmap_surface = dri2_drm_create_pixmap_surface,.destroy_surface = dri2_drm_destroy_surface,.create_image = dri2_drm_create_image_khr,.swap_buffers = dri2_drm_swap_buffers,.query_buffer_age = dri2_drm_query_buffer_age,.get_dri_drawable = dri2_surface_get_dri_drawable,
};

gbm_create_device

        gbm = gbm_create_device(dri2_dpy->fd);   //创建gbm device,用于通过cardX申请buffergbm = _gbm_create_device(fd);   //如果私有的,可以设置GBM_BACKEND,让libgbm去load backend,否则就是load gbm_dri.so,对应的就是dri_device_create(fd);dev = backend->create_device(fd);dri_device_create(fd);  //就是填充gbm_dri_device结构体dri,详见下。dri_screen_create(dri);  driver_name = loader_get_driver_for_fd(dri->base.fd);  //获取driver name,驱动注册时候的名字。如果是virtio-gpu,那么driver_name就是virtio-gpureturn dri_screen_create_dri2(dri, driver_name);dri_load_driver(dri);extensions = dri_open_driver(dri);//加载对应的gpu驱动,并且返回__DRIextension, dri->driver = dlopen的virtio_gpu_dir.sodlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL); // Temporarily work around dri driver libs that need symbols in libglapi but don't automatically link it in. 实属不理解,该函数讲打开对应的库,主要用来加载库中的符号return loader_open_driver(dri->driver_name, &dri->driver, search_path_vars);// Opens a DRI driver using its driver name, returning the __DRIextension entrypoints. 这个driver不是bsp的driver,而是用户层是so库,也就是gpu的驱动是在userspace的,加载对应的库,并加载对应的__driDriverExtensions!driver = dlopen(virtio_gpu_dri.so) //不同厂家的so不一样!extensions = dlsym(driver, );  //默认是__driDriverExtensions,__driDriverGetExtensions_virtio_gpureturn extensions;dri_bind_extensions(dri, gbm_dri_device_extensions, size, extensions); //将extensions 绑定到 dri 的对应的 core 和 dri2 上面, extensions是从dlopen driver,dlsym 得到的_driDriverExtensions,此时dri->dri2和dri->core已经赋值成功。见下面一部分,是core和dri2的定义
///
DRI_Core/DRI_DRI2
static struct dri_extension_match gbm_dri_device_extensions[] = {{ __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), false },{ __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2), false },
};
///dri->driver_extensions = extensions; //最后保留下对应的地址dri->loader_extensions = gbm_dri_screen_extensions; //再保留下定义的地址。dri->screen = dri->dri2->createNewScreen2(0, dri->base.fd,dri->loader_extensions,dri->driver_extensions,&dri->driver_configs, dri);driCreateNewScreen2  // This is the first entrypoint in the driver called by the DRI driver loader after dlopen()ing it. It's used to create global state for the driver across contexts on the same Display.如注释,这是在dlopen用户态gpu驱动以后的第一个被调用的驱动函数,它用于在同一display对象上跨上下文为驱动程序创建全局状态。文件位置在src/mesa/drvier/dri/common/dri_util.cpsp->driver = ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable; // psp是__DRIscreen 指针,这里会失败!!不过没关系。///
driver_extensions->name为:
DRI_Core
DRI_IMAGE_DRIVER
DRI_DRI2
DRI_ConfigOptionsextensions->name为:
DRI_IMAGE_LOOKUP
DRI_UseInvalidate
DRI_DRI2Loader
DRI_IMAGE_LOADER
DRI_SWRastLoader
///setupLoaderExtensions(psp, extensions); //任然是绑定一些函数。/* Option parsing before ->InitScreen(), as some options apply there. */driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions, ARRAY_SIZE(__dri2ConfigOptions));driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2", NULL, NULL, 0, NULL, 0);*driver_configs = psp->driver->InitScreen(psp);调用的是gallium里面的dri2.c文件的galliumdrm_driver_api,具体位置是mesa/src/gallium/frontends/dri/dri2.c;returns the struct gl_config supported by this driver.########dri2_init_screen 最终返回的是gl_config结构体。内容见下块!!!########...return psp;//返回的是__DRIscreen *psp;接着是基于psp,也就是Pre-screen-private driver information结构体指针,填充max_gl_es2_version,max_gl_core_version,max_gl_compat_version以及api_maskextensions = dri->core->getExtensions(dri->screen);dri_bind_extensions(dri, dri_core_extensions, ARRAY_SIZE(dri_core_extensions), extensions);return gbm;##########关于gallium里面函数钩子。
/*** DRI driver virtual function table.** DRI versions differ in their implementation of init_screen and swap_buffers.*/
const struct __DriverAPIRec galliumdrm_driver_api = {.InitScreen = dri2_init_screen,.DestroyScreen = dri_destroy_screen,.CreateContext = dri_create_context,.DestroyContext = dri_destroy_context,.CreateBuffer = dri2_create_buffer,.DestroyBuffer = dri_destroy_buffer,.MakeCurrent = dri_make_current,.UnbindContext = dri_unbind_context,.AllocateBuffer = dri2_allocate_buffer,.ReleaseBuffer  = dri2_release_buffer,
};

dri2_init_screen

关于gallium里面的dri2_init_screen,这个是驱动部分的具体实现,是createNewScreen的具体实现,返回的是 gl_config 结构体。

//mesa/src/gallium/frontends/dri/dri2.c
static const __DRIconfig **
dri2_init_screen(__DRIscreen * sPriv)
{const __DRIconfig **configs;struct dri_screen *screen;struct pipe_screen *pscreen = NULL;
...if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) { //主要填充screen->dev,见下文dri_init_options(screen);pipe_loader_load_options(screen->dev);dri_fill_st_options(screen);//判断驱动是否支持这些功能,如这个application是否支持disable_blend_func_extended, force_glsl_version, allow_glsl_relaxed_es,force_gl_vendor等等,并且返回唯一hash来指定。代码是dri_screen.cdriComputeOptionsSha1(optionCache, options->config_options_sha1);pscreen = pipe_loader_create_screen(screen->dev);  //create_screen继续跟踪util_cpu_detect()call_once(&cpu_once_flag, util_cpu_detect_once);// check cpu特性?pipe_loader_load_options(dev); //同样的参数又来了一遍,感觉不太重要return dev->ops->create_screen(dev,&config);   //pipe_loader_drm_create_screen,见下文pipe_loader_drm_create_screenreturn ddev->dd->create_screen(ddev->fd, config);}
...此时就已经有了pscreen,整个通路已经打通。screen 是 dri_screen指针, pscreen是pipe_screen指针。screen->throttle = pscreen->get_param(pscreen, PIPE_CAP_THROTTLE);/* set up the dri extension list for this screen based on its underlying gallium screen;s capabilities;根据pscreen设置screen的一些extensions。包括最重要的dmabuf,还有对应prime共享机制。createImageFromFs, createImageFormDmaBufs 等等。dri2_init_screen_extensions(screen, pscreen, false);configs = dri_init_screen_helper(screen, pscreen);screen ->base.screen = pscreen;...screen ->st_api = st_gl_api_create(); //对应实现在st_manager.c...dri_postprocessing_init(screen); //screen->st_api->query_versions(...); //设置screen的一些version,gl的,gles的。return dir_fill_in_modes(screen); //返回_DRIconfigscreen->can_share_buffer = truscreen->auto_fake_front = dri_with_format(sPriv);screen->broken_invalidate = !sPriv->dri2.useInvalidate;screen->lookup_egl_image = dri2_lookup_egl_image;return configs; //最终返回给是一个configs
}######
pipe_loader_drm_probe_fdpipe_loader_drm_probe_fd_nodup(dev, new_fd);struct pipe_loader_drm_device *ddev;loader_get_pci_id_for_fd  //就是拿vendor_id和chip_iddrm_get_pci_id_for_fddrmGetDevice2(fd, 0 ,&device)*vendor_id = device->deviceinfo.pci->vendor_id;*chip_id = device->deviceinfo.pci->device_id;drmFreeDevice(device);ddev->base.ops = &pipe_loader_drm_ops; //详见下ddev->base.driver_name = loader_get_driver_for_fd(fd);//通过fd获取drver的名字。kernel驱动里面设置的。modetest -M xxx这个nameddev->dd = get_driver_descriptor(ddev->base.driver_name, plib);//返回的是drm_driver_descriptor,硬件强相关。具体驱动实现?if (strcmp(driver_descriptors[i]->driver_name, driver_name) == 0)return driver_descriptors[i]; //具体看驱动是哪个,我们是virtio_gpu_driver_descriptor. 定义在drm_helper_public.h,具体实现可看到drm_help.h里面的#define DEFINE_DRM_DRIVER_DESCRIPTOR*dev = &ddev->base; //此时dev有了ops,drvier_name,type, vendor_id, chip_id等硬件信息。#####
//pipe_loader_drm.c
static const struct pipe_loader_ops pipe_loader_drm_ops = {.create_screen = pipe_loader_drm_create_screen,.get_driconf = pipe_loader_drm_get_driconf,.release = pipe_loader_drm_release
};pipe_loader_drm_create_screen(pipe_loader_device *dev, pipe_screen_config *config)return ddev->dd->create_screen(ddev->fd,config);pipe_vritio_gpu_create_screen(fd, *config);//对应实现在drm_helper.hstruct pipe_screen *screen;screen = virgl_drm_screen_create(fd, config);//对应实现在virgl_drm_winsys.c 终于到了winsys层!...创建一个pipe_screen指针 和 fd之间的hash表关系,后面就可以通过fd找到对应的pipe_screen...如果不是第一次创建,则会对virgl_screen的refcnt++;否则如下strcut virgl_winsys *vws;vws = virgl_drm_winsys_create(fd); //首先是通过drmioctl对param功能的确认,见下文strcut virgl_drm_winsys *qdws;ret = drmIoctl(drmFD, DRM_IOCTL_VIRTGPU_GETPARAM, &getparam); //确认这些功能支持与否drm_version = virgl_drm_get_version(fd); //就是drmGetVersion再加点自己的东西,就是个版本设置。接下来就是初始化qdws,这个东西很重要,就是最最最hal的地方!直接调用的就是ioctlreturn &qdws->base;           pscreen = virgl_create_screen(vws, config);完整的初始化virgl_screen,并把vws,也就是上面的qdws->base放入screen->vws...vwm->get_caps();fixup_formats();...slab_create_parent()virgl_disk_cache_create();return &screen->base;...会把这个pscreen塞入hash,方便后续找到,复用。当然也绑定了pscreen->destroy函数为virgl_drm_screen_destroy;最终返回的是pscreenreturn screen ? debug_screen_wrap(screen) : NULL;又对这个screen进行了四次封装,这个screen真的波折太多:screen = ddebug_screen_create(screen);screen = rbug_screen_create(screen);screen = trace_screen_create(screen);screen = noop_screen_create(screen);return screen //总算结束了!// virgl_drm_winsys.h params
struct param params[] = { PARAM(VIRTGPU_PARAM_3D_FEATURES),PARAM(VIRTGPU_PARAM_CAPSET_QUERY_FIX),PARAM(VIRTGPU_PARAM_RESOURCE_BLOB),PARAM(VIRTGPU_PARAM_HOST_VISIBLE),PARAM(VIRTGPU_PARAM_CROSS_DEVICE)
};########st_api
//st_manager.c
static const struct st_api st_gl_api = {.name = "Mesa " PACKAGE_VERSION,.api = ST_API_OPENGL,.profile_mask = ST_PROFILE_DEFAULT_MASK |ST_PROFILE_OPENGL_CORE_MASK |ST_PROFILE_OPENGL_ES1_MASK |ST_PROFILE_OPENGL_ES2_MASK |0,.feature_mask = ST_API_FEATURE_MS_VISUALS_MASK,.destroy = st_api_destroy,.query_versions = st_api_query_versions,.create_context = st_api_create_context,.make_current = st_api_make_current,.get_current = st_api_get_current,.destroy_drawable = st_api_destroy_drawable,
};

上面这段大致1.初始化vws和pscreen,也就是真正的hal接口了。  pscreen拥有一切对下的接口。牛

core和dir2的实现在dri_util.c里面

/** Core interface */
const __DRIcoreExtension driCoreExtension = {.base = { __DRI_CORE, 2 },.createNewScreen            = NULL,.destroyScreen              = driDestroyScreen,.getExtensions              = driGetExtensions,.getConfigAttrib            = driGetConfigAttrib,.indexConfigAttrib          = driIndexConfigAttrib,.createNewDrawable          = NULL,.destroyDrawable            = driDestroyDrawable,.swapBuffers                = driSwapBuffers, /* swrast */.createNewContext           = driCreateNewContext, /* swrast */.copyContext                = driCopyContext,.destroyContext             = driDestroyContext,.bindContext                = driBindContext,.unbindContext              = driUnbindContext
};/** DRI2 interface */
const __DRIdri2Extension driDRI2Extension = {.base = { __DRI_DRI2, 4 },.createNewScreen            = dri2CreateNewScreen,.createNewDrawable          = driCreateNewDrawable,.createNewContext           = driCreateNewContext,.getAPIMask                 = driGetAPIMask,.createNewContextForAPI     = driCreateNewContextForAPI,.allocateBuffer             = dri2AllocateBuffer,.releaseBuffer              = dri2ReleaseBuffer,.createContextAttribs       = driCreateContextAttribs,.createNewScreen2           = driCreateNewScreen2,
};

dri_initialize_wayland

EGLBoolean
dri2_initialize_wayland(_EGLDisplay *disp)
{if (disp->Options.ForceSoftware)return dri2_initialize_wayland_swrast(disp);elsereturn dri2_initialize_wayland_drm(disp);......wayland client的标准调用相关就写了dri2_dpy -> fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);//目的就是返回fd,但是如果有多个支持渲染的节点,貌似会和weston用到的node有区别。看样子是合成和渲染分card执行,换句话也就是支持多card。dev = _eglAddDevice(dri2_dpy->fd , false);...剩下这段和dri2_initialize_drm一致...dri_wl_setup_swap_interval(disp); //设置interval,也就是多少个vsync做绘画。
}

接下一篇:display: mesa: eglapi接口:bind/query api_maze的专栏-CSDN博客

display: mesa: eglapi接口:getdisplayinitialize相关推荐

  1. 显示器驱动有什么用_科普一下:电脑显示器用什么接口好,主流接口有哪些?...

    如今是新的"视"界,生活中总与各种屏幕打交道,难免会遇到选择视频接线的问题,要想搞清楚这点,我们只要通过了解现今常用的几种视频接线就会有个大致的认识. 经常会有一些朋友困扰,电脑显 ...

  2. 显示设备的接口分类:VGA,HDMI,DVI等等

    显示设备的接口分类:VGA,HDMI,DVI等等 一分钟速读-常见的外部显示接口 VGA是比较老的接口是模拟信号,所以一般来说效果比较差,现在主流的显示器用的比较少. DVI是数字信号,高分辨率下更加 ...

  3. 全志T7 Display驱动简介

    可先阅读<Sunxi_display2模块使用文档.pdf>.<图形开发用户指南.pdf> DE:Display Engine Write-Back:capture data ...

  4. Windows10 pc使用Apple Studio Display显示器设置

    近期,工作需要,有购买了台Apple Studio Display显示器,大概花了约1.5w,连接windows台式机,显卡为NVIDA GTX-1660,而Apple Studio Display只 ...

  5. 略过天涯 深入浅出VGA和DVI接口【转】

    本文转载自:http://www.cnblogs.com/lueguo/p/3373649.html 由CrazyBingo修改-- 前言:目前显示器的主流接口是VGA.DVI以及HDMI,再加上一个 ...

  6. 【科普】显示器VGA、DVI、HDMI、DP等各种接口详细科普

    由于显示器接口十分众多,比如说VGA.DVI.HDMI.DP等等等等,而每个接口都有各种型号,很容易让小白绕晕,因此这里详细介绍一下各个接口以及接口的相关型号参数. 目录 一.VGA接口 二.DVI接 ...

  7. 华三h3c交换机最详细的配置实例手册_华为/思科/华三基本命令对比

    很多朋友反映,对华为/思科/华三交换机配置命令有些分不清楚,那么今天弱电君和大家来看下他们的区别在哪里,这里对命令做了个汇总,平时对命令不熟的朋友这次可以看下. CISCO H3C HUAWEI 描述 ...

  8. 37张图详解MAC地址、以太网、二层转发、VLAN

    目录 MAC 地址 每个网卡或三层网口都有一个 MAC 地址, MAC 地址是烧录到硬件上,因此也称为硬件地址.MAC 地址作为数据链路设备的地址标识符,需要保证网络中的每个 MAC 地址都是唯一的, ...

  9. 华为交换机配置命令 华为QuidWay交换机配置命令手册

    华为交换机配置,仅供参考: 1.开始建立本地配置环境,将主机的串口通过配置电缆与以太网交换机的Console口连接. 在主机上运行终端仿真程序(如Windows的超级终端等),设置终端通信参数为:波特 ...

最新文章

  1. sql server 内存初探
  2. [递归]递归问题解题思路
  3. linux vmware 安装后无法桥接到物理网卡的解决办法
  4. 《跟我一起写Makefile》读书笔记(1)
  5. tomcat7 IP限制配置
  6. Android通过Wifi来调试你的应用
  7. c++ inline 函数及变量
  8. 计算机一级等级软件未来教育 手机版,计算机一级模拟考试软件手机版
  9. HP520 笔记本 驱动安装的一些问题
  10. 多变量微积分笔记22——空间曲面的通量
  11. Machine Learning/Random Projection
  12. 产品经理不再纸上谈兵——关于用户默认头像的思考
  13. z-index什么意思
  14. geotools中等值面的生成与OL3中的展示
  15. c语言任何一个大于6的偶数均可表示为两个素数之和,C语言:验证哥德巴赫猜想:任何一个大于6的偶数均可表示为2个素数之和...
  16. 三类最常用的数据分析工具,你用过哪一类?
  17. ffmpeg 命令学习
  18. Python3.x+Pyqt5实现界面编程浏览网页
  19. 1035 插入与归并(C++)
  20. 【双十二】2020年双十二哪些笔记本值得推荐?

热门文章

  1. [转帖]ARM 相关内容
  2. django1.10+mysql/connector 2.1.3运行polls demo的问题
  3. 腾讯如何做 Code Review的?万字详解!
  4. LVGL 之 windows 上 lvgl 模拟器基于 Visual Studio 搭建方法的简单整理
  5. 如何准备阿里的社招技术面试
  6. 电动助力转向EPS(二)——理论公式推导及simulink模型
  7. 【机器视觉】视觉工程师必须知道的工业相机50问
  8. 计算机网络中级,计算机网络(中级)
  9. 如何隐藏在不和谐状态下玩的游戏
  10. 关于飞机绕地球飞行一圈的加油问题