1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2011 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19bf215546Sopenharmony_ci * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20bf215546Sopenharmony_ci * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci * Authors: 25bf215546Sopenharmony_ci * Kristian Høgsberg <krh@bitplanet.net> 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include <stdint.h> 29bf215546Sopenharmony_ci#include <stdlib.h> 30bf215546Sopenharmony_ci#include <stdio.h> 31bf215546Sopenharmony_ci#include <string.h> 32bf215546Sopenharmony_ci#include <xf86drm.h> 33bf215546Sopenharmony_ci#include <dlfcn.h> 34bf215546Sopenharmony_ci#include <sys/types.h> 35bf215546Sopenharmony_ci#include <sys/stat.h> 36bf215546Sopenharmony_ci#include <fcntl.h> 37bf215546Sopenharmony_ci#include <unistd.h> 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "util/os_file.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "egl_dri2.h" 42bf215546Sopenharmony_ci#include "loader.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_cistatic struct gbm_bo * 45bf215546Sopenharmony_cilock_front_buffer(struct gbm_surface *_surf) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci struct gbm_dri_surface *surf = gbm_dri_surface(_surf); 48bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = surf->dri_private; 49bf215546Sopenharmony_ci struct gbm_dri_device *device = gbm_dri_device(_surf->gbm); 50bf215546Sopenharmony_ci struct gbm_bo *bo; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci if (dri2_surf->current == NULL) { 53bf215546Sopenharmony_ci _eglError(EGL_BAD_SURFACE, "no front buffer"); 54bf215546Sopenharmony_ci return NULL; 55bf215546Sopenharmony_ci } 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci bo = dri2_surf->current->bo; 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci if (device->dri2) { 60bf215546Sopenharmony_ci dri2_surf->current->locked = true; 61bf215546Sopenharmony_ci dri2_surf->current = NULL; 62bf215546Sopenharmony_ci } 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci return bo; 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_cistatic void 68bf215546Sopenharmony_cirelease_buffer(struct gbm_surface *_surf, struct gbm_bo *bo) 69bf215546Sopenharmony_ci{ 70bf215546Sopenharmony_ci struct gbm_dri_surface *surf = gbm_dri_surface(_surf); 71bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = surf->dri_private; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 74bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].bo == bo) { 75bf215546Sopenharmony_ci dri2_surf->color_buffers[i].locked = false; 76bf215546Sopenharmony_ci break; 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistatic int 82bf215546Sopenharmony_cihas_free_buffers(struct gbm_surface *_surf) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci struct gbm_dri_surface *surf = gbm_dri_surface(_surf); 85bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = surf->dri_private; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) 88bf215546Sopenharmony_ci if (!dri2_surf->color_buffers[i].locked) 89bf215546Sopenharmony_ci return 1; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci return 0; 92bf215546Sopenharmony_ci} 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_cistatic bool 95bf215546Sopenharmony_cidri2_drm_config_is_compatible(struct dri2_egl_display *dri2_dpy, 96bf215546Sopenharmony_ci const __DRIconfig *config, 97bf215546Sopenharmony_ci struct gbm_surface *surface) 98bf215546Sopenharmony_ci{ 99bf215546Sopenharmony_ci const struct gbm_dri_visual *visual = NULL; 100bf215546Sopenharmony_ci int shifts[4]; 101bf215546Sopenharmony_ci unsigned int sizes[4]; 102bf215546Sopenharmony_ci bool is_float; 103bf215546Sopenharmony_ci int i; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci /* Check that the EGLConfig being used to render to the surface is 106bf215546Sopenharmony_ci * compatible with the surface format. Since mixing ARGB and XRGB of 107bf215546Sopenharmony_ci * otherwise-compatible formats is relatively common, explicitly allow 108bf215546Sopenharmony_ci * this. 109bf215546Sopenharmony_ci */ 110bf215546Sopenharmony_ci dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci dri2_get_render_type_float(dri2_dpy->core, config, &is_float); 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci for (i = 0; i < dri2_dpy->gbm_dri->num_visuals; i++) { 115bf215546Sopenharmony_ci visual = &dri2_dpy->gbm_dri->visual_table[i]; 116bf215546Sopenharmony_ci if (visual->gbm_format == surface->v0.format) 117bf215546Sopenharmony_ci break; 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci if (i == dri2_dpy->gbm_dri->num_visuals) 121bf215546Sopenharmony_ci return false; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci if (shifts[0] != visual->rgba_shifts.red || 124bf215546Sopenharmony_ci shifts[1] != visual->rgba_shifts.green || 125bf215546Sopenharmony_ci shifts[2] != visual->rgba_shifts.blue || 126bf215546Sopenharmony_ci (shifts[3] > -1 && visual->rgba_shifts.alpha > -1 && 127bf215546Sopenharmony_ci shifts[3] != visual->rgba_shifts.alpha) || 128bf215546Sopenharmony_ci sizes[0] != visual->rgba_sizes.red || 129bf215546Sopenharmony_ci sizes[1] != visual->rgba_sizes.green || 130bf215546Sopenharmony_ci sizes[2] != visual->rgba_sizes.blue || 131bf215546Sopenharmony_ci (sizes[3] > 0 && visual->rgba_sizes.alpha > 0 && 132bf215546Sopenharmony_ci sizes[3] != visual->rgba_sizes.alpha) || 133bf215546Sopenharmony_ci is_float != visual->is_float) { 134bf215546Sopenharmony_ci return false; 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci return true; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_cistatic _EGLSurface * 141bf215546Sopenharmony_cidri2_drm_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, 142bf215546Sopenharmony_ci void *native_surface, const EGLint *attrib_list) 143bf215546Sopenharmony_ci{ 144bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 145bf215546Sopenharmony_ci struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 146bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf; 147bf215546Sopenharmony_ci struct gbm_surface *surface = native_surface; 148bf215546Sopenharmony_ci struct gbm_dri_surface *surf; 149bf215546Sopenharmony_ci const __DRIconfig *config; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci dri2_surf = calloc(1, sizeof *dri2_surf); 152bf215546Sopenharmony_ci if (!dri2_surf) { 153bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 154bf215546Sopenharmony_ci return NULL; 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, 158bf215546Sopenharmony_ci attrib_list, false, native_surface)) 159bf215546Sopenharmony_ci goto cleanup_surf; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT, 162bf215546Sopenharmony_ci dri2_surf->base.GLColorspace); 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci if (!config) { 165bf215546Sopenharmony_ci _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); 166bf215546Sopenharmony_ci goto cleanup_surf; 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci if (!dri2_drm_config_is_compatible(dri2_dpy, config, surface)) { 170bf215546Sopenharmony_ci _eglError(EGL_BAD_MATCH, "EGL config not compatible with GBM format"); 171bf215546Sopenharmony_ci goto cleanup_surf; 172bf215546Sopenharmony_ci } 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci surf = gbm_dri_surface(surface); 175bf215546Sopenharmony_ci dri2_surf->gbm_surf = surf; 176bf215546Sopenharmony_ci dri2_surf->base.Width = surf->base.v0.width; 177bf215546Sopenharmony_ci dri2_surf->base.Height = surf->base.v0.height; 178bf215546Sopenharmony_ci surf->dri_private = dri2_surf; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf->gbm_surf)) 181bf215546Sopenharmony_ci goto cleanup_surf; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci return &dri2_surf->base; 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci cleanup_surf: 186bf215546Sopenharmony_ci free(dri2_surf); 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci return NULL; 189bf215546Sopenharmony_ci} 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_cistatic _EGLSurface * 192bf215546Sopenharmony_cidri2_drm_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf, 193bf215546Sopenharmony_ci void *native_window, const EGLint *attrib_list) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci /* From the EGL_MESA_platform_gbm spec, version 5: 196bf215546Sopenharmony_ci * 197bf215546Sopenharmony_ci * It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy> 198bf215546Sopenharmony_ci * that belongs to the GBM platform. Any such call fails and generates 199bf215546Sopenharmony_ci * EGL_BAD_PARAMETER. 200bf215546Sopenharmony_ci */ 201bf215546Sopenharmony_ci _eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on GBM"); 202bf215546Sopenharmony_ci return NULL; 203bf215546Sopenharmony_ci} 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_cistatic EGLBoolean 206bf215546Sopenharmony_cidri2_drm_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 209bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 214bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].bo) 215bf215546Sopenharmony_ci gbm_bo_destroy(dri2_surf->color_buffers[i].bo); 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci dri2_egl_surface_free_local_buffers(dri2_surf); 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci dri2_fini_surface(surf); 221bf215546Sopenharmony_ci free(surf); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci return EGL_TRUE; 224bf215546Sopenharmony_ci} 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_cistatic int 227bf215546Sopenharmony_ciget_back_bo(struct dri2_egl_surface *dri2_surf) 228bf215546Sopenharmony_ci{ 229bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 230bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 231bf215546Sopenharmony_ci struct gbm_dri_surface *surf = dri2_surf->gbm_surf; 232bf215546Sopenharmony_ci int age = 0; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci if (dri2_surf->back == NULL) { 235bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 236bf215546Sopenharmony_ci if (!dri2_surf->color_buffers[i].locked && 237bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age >= age) { 238bf215546Sopenharmony_ci dri2_surf->back = &dri2_surf->color_buffers[i]; 239bf215546Sopenharmony_ci age = dri2_surf->color_buffers[i].age; 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci if (dri2_surf->back == NULL) 245bf215546Sopenharmony_ci return -1; 246bf215546Sopenharmony_ci if (dri2_surf->back->bo == NULL) { 247bf215546Sopenharmony_ci if (surf->base.v0.modifiers) 248bf215546Sopenharmony_ci dri2_surf->back->bo = gbm_bo_create_with_modifiers(&dri2_dpy->gbm_dri->base, 249bf215546Sopenharmony_ci surf->base.v0.width, 250bf215546Sopenharmony_ci surf->base.v0.height, 251bf215546Sopenharmony_ci surf->base.v0.format, 252bf215546Sopenharmony_ci surf->base.v0.modifiers, 253bf215546Sopenharmony_ci surf->base.v0.count); 254bf215546Sopenharmony_ci else { 255bf215546Sopenharmony_ci unsigned flags = surf->base.v0.flags; 256bf215546Sopenharmony_ci if (dri2_surf->base.ProtectedContent) 257bf215546Sopenharmony_ci flags |= GBM_BO_USE_PROTECTED; 258bf215546Sopenharmony_ci dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base, 259bf215546Sopenharmony_ci surf->base.v0.width, 260bf215546Sopenharmony_ci surf->base.v0.height, 261bf215546Sopenharmony_ci surf->base.v0.format, 262bf215546Sopenharmony_ci flags); 263bf215546Sopenharmony_ci } 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci if (dri2_surf->back->bo == NULL) 267bf215546Sopenharmony_ci return -1; 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci return 0; 270bf215546Sopenharmony_ci} 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_cistatic int 273bf215546Sopenharmony_ciget_swrast_front_bo(struct dri2_egl_surface *dri2_surf) 274bf215546Sopenharmony_ci{ 275bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 276bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 277bf215546Sopenharmony_ci struct gbm_dri_surface *surf = dri2_surf->gbm_surf; 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci if (dri2_surf->current == NULL) { 280bf215546Sopenharmony_ci assert(!dri2_surf->color_buffers[0].locked); 281bf215546Sopenharmony_ci dri2_surf->current = &dri2_surf->color_buffers[0]; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci if (dri2_surf->current->bo == NULL) 285bf215546Sopenharmony_ci dri2_surf->current->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base, 286bf215546Sopenharmony_ci surf->base.v0.width, 287bf215546Sopenharmony_ci surf->base.v0.height, 288bf215546Sopenharmony_ci surf->base.v0.format, 289bf215546Sopenharmony_ci surf->base.v0.flags); 290bf215546Sopenharmony_ci if (dri2_surf->current->bo == NULL) 291bf215546Sopenharmony_ci return -1; 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci return 0; 294bf215546Sopenharmony_ci} 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_cistatic void 297bf215546Sopenharmony_ciback_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer) 298bf215546Sopenharmony_ci{ 299bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 300bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 301bf215546Sopenharmony_ci struct gbm_dri_bo *bo; 302bf215546Sopenharmony_ci int name, pitch; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci bo = gbm_dri_bo(dri2_surf->back->bo); 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name); 307bf215546Sopenharmony_ci dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch); 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci buffer->attachment = __DRI_BUFFER_BACK_LEFT; 310bf215546Sopenharmony_ci buffer->name = name; 311bf215546Sopenharmony_ci buffer->pitch = pitch; 312bf215546Sopenharmony_ci buffer->cpp = 4; 313bf215546Sopenharmony_ci buffer->flags = 0; 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_cistatic __DRIbuffer * 317bf215546Sopenharmony_cidri2_drm_get_buffers_with_format(__DRIdrawable *driDrawable, 318bf215546Sopenharmony_ci int *width, int *height, 319bf215546Sopenharmony_ci unsigned int *attachments, int count, 320bf215546Sopenharmony_ci int *out_count, void *loaderPrivate) 321bf215546Sopenharmony_ci{ 322bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 323bf215546Sopenharmony_ci int i, j; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci for (i = 0, j = 0; i < 2 * count; i += 2, j++) { 326bf215546Sopenharmony_ci __DRIbuffer *local; 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci assert(attachments[i] < __DRI_BUFFER_COUNT); 329bf215546Sopenharmony_ci assert(j < ARRAY_SIZE(dri2_surf->buffers)); 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci switch (attachments[i]) { 332bf215546Sopenharmony_ci case __DRI_BUFFER_BACK_LEFT: 333bf215546Sopenharmony_ci if (get_back_bo(dri2_surf) < 0) { 334bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer"); 335bf215546Sopenharmony_ci return NULL; 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]); 338bf215546Sopenharmony_ci break; 339bf215546Sopenharmony_ci default: 340bf215546Sopenharmony_ci local = dri2_egl_surface_alloc_local_buffer(dri2_surf, attachments[i], 341bf215546Sopenharmony_ci attachments[i + 1]); 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci if (!local) { 344bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "failed to allocate local buffer"); 345bf215546Sopenharmony_ci return NULL; 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci dri2_surf->buffers[j] = *local; 348bf215546Sopenharmony_ci break; 349bf215546Sopenharmony_ci } 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci *out_count = j; 353bf215546Sopenharmony_ci if (j == 0) 354bf215546Sopenharmony_ci return NULL; 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci *width = dri2_surf->base.Width; 357bf215546Sopenharmony_ci *height = dri2_surf->base.Height; 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci return dri2_surf->buffers; 360bf215546Sopenharmony_ci} 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_cistatic __DRIbuffer * 363bf215546Sopenharmony_cidri2_drm_get_buffers(__DRIdrawable * driDrawable, 364bf215546Sopenharmony_ci int *width, int *height, 365bf215546Sopenharmony_ci unsigned int *attachments, int count, 366bf215546Sopenharmony_ci int *out_count, void *loaderPrivate) 367bf215546Sopenharmony_ci{ 368bf215546Sopenharmony_ci unsigned int *attachments_with_format; 369bf215546Sopenharmony_ci __DRIbuffer *buffer; 370bf215546Sopenharmony_ci const unsigned int format = 32; 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci attachments_with_format = calloc(count, 2 * sizeof(unsigned int)); 373bf215546Sopenharmony_ci if (!attachments_with_format) { 374bf215546Sopenharmony_ci *out_count = 0; 375bf215546Sopenharmony_ci return NULL; 376bf215546Sopenharmony_ci } 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci for (int i = 0; i < count; ++i) { 379bf215546Sopenharmony_ci attachments_with_format[2*i] = attachments[i]; 380bf215546Sopenharmony_ci attachments_with_format[2*i + 1] = format; 381bf215546Sopenharmony_ci } 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci buffer = 384bf215546Sopenharmony_ci dri2_drm_get_buffers_with_format(driDrawable, 385bf215546Sopenharmony_ci width, height, 386bf215546Sopenharmony_ci attachments_with_format, count, 387bf215546Sopenharmony_ci out_count, loaderPrivate); 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci free(attachments_with_format); 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci return buffer; 392bf215546Sopenharmony_ci} 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_cistatic int 395bf215546Sopenharmony_cidri2_drm_image_get_buffers(__DRIdrawable *driDrawable, 396bf215546Sopenharmony_ci unsigned int format, 397bf215546Sopenharmony_ci uint32_t *stamp, 398bf215546Sopenharmony_ci void *loaderPrivate, 399bf215546Sopenharmony_ci uint32_t buffer_mask, 400bf215546Sopenharmony_ci struct __DRIimageList *buffers) 401bf215546Sopenharmony_ci{ 402bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 403bf215546Sopenharmony_ci struct gbm_dri_bo *bo; 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci if (get_back_bo(dri2_surf) < 0) 406bf215546Sopenharmony_ci return 0; 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci bo = gbm_dri_bo(dri2_surf->back->bo); 409bf215546Sopenharmony_ci buffers->image_mask = __DRI_IMAGE_BUFFER_BACK; 410bf215546Sopenharmony_ci buffers->back = bo->image; 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci return 1; 413bf215546Sopenharmony_ci} 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_cistatic void 416bf215546Sopenharmony_cidri2_drm_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 417bf215546Sopenharmony_ci{ 418bf215546Sopenharmony_ci (void) driDrawable; 419bf215546Sopenharmony_ci (void) loaderPrivate; 420bf215546Sopenharmony_ci} 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_cistatic EGLBoolean 423bf215546Sopenharmony_cidri2_drm_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) 424bf215546Sopenharmony_ci{ 425bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 426bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci if (!dri2_dpy->flush) { 429bf215546Sopenharmony_ci dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); 430bf215546Sopenharmony_ci return EGL_TRUE; 431bf215546Sopenharmony_ci } 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci if (dri2_surf->current) 434bf215546Sopenharmony_ci _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers"); 435bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) 436bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].age > 0) 437bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age++; 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci /* Make sure we have a back buffer in case we're swapping without 440bf215546Sopenharmony_ci * ever rendering. */ 441bf215546Sopenharmony_ci if (get_back_bo(dri2_surf) < 0) 442bf215546Sopenharmony_ci return _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers"); 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci dri2_surf->current = dri2_surf->back; 445bf215546Sopenharmony_ci dri2_surf->current->age = 1; 446bf215546Sopenharmony_ci dri2_surf->back = NULL; 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci dri2_flush_drawable_for_swapbuffers(disp, draw); 449bf215546Sopenharmony_ci dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci return EGL_TRUE; 452bf215546Sopenharmony_ci} 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_cistatic EGLint 455bf215546Sopenharmony_cidri2_drm_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface) 456bf215546Sopenharmony_ci{ 457bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface); 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci if (get_back_bo(dri2_surf) < 0) { 460bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age"); 461bf215546Sopenharmony_ci return -1; 462bf215546Sopenharmony_ci } 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci return dri2_surf->back->age; 465bf215546Sopenharmony_ci} 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_cistatic _EGLImage * 468bf215546Sopenharmony_cidri2_drm_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, 469bf215546Sopenharmony_ci EGLClientBuffer buffer, const EGLint *attr_list) 470bf215546Sopenharmony_ci{ 471bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 472bf215546Sopenharmony_ci struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer); 473bf215546Sopenharmony_ci struct dri2_egl_image *dri2_img; 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci dri2_img = malloc(sizeof *dri2_img); 476bf215546Sopenharmony_ci if (!dri2_img) { 477bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap"); 478bf215546Sopenharmony_ci return NULL; 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci _eglInitImage(&dri2_img->base, disp); 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img); 484bf215546Sopenharmony_ci if (dri2_img->dri_image == NULL) { 485bf215546Sopenharmony_ci free(dri2_img); 486bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap"); 487bf215546Sopenharmony_ci return NULL; 488bf215546Sopenharmony_ci } 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci return &dri2_img->base; 491bf215546Sopenharmony_ci} 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_cistatic _EGLImage * 494bf215546Sopenharmony_cidri2_drm_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, 495bf215546Sopenharmony_ci EGLClientBuffer buffer, const EGLint *attr_list) 496bf215546Sopenharmony_ci{ 497bf215546Sopenharmony_ci switch (target) { 498bf215546Sopenharmony_ci case EGL_NATIVE_PIXMAP_KHR: 499bf215546Sopenharmony_ci return dri2_drm_create_image_khr_pixmap(disp, ctx, buffer, attr_list); 500bf215546Sopenharmony_ci default: 501bf215546Sopenharmony_ci return dri2_create_image_khr(disp, ctx, target, buffer, attr_list); 502bf215546Sopenharmony_ci } 503bf215546Sopenharmony_ci} 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_cistatic int 506bf215546Sopenharmony_cidri2_drm_authenticate(_EGLDisplay *disp, uint32_t id) 507bf215546Sopenharmony_ci{ 508bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci return drmAuthMagic(dri2_dpy->fd, id); 511bf215546Sopenharmony_ci} 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_cistatic void 514bf215546Sopenharmony_ciswrast_put_image2(__DRIdrawable *driDrawable, 515bf215546Sopenharmony_ci int op, 516bf215546Sopenharmony_ci int x, 517bf215546Sopenharmony_ci int y, 518bf215546Sopenharmony_ci int width, 519bf215546Sopenharmony_ci int height, 520bf215546Sopenharmony_ci int stride, 521bf215546Sopenharmony_ci char *data, 522bf215546Sopenharmony_ci void *loaderPrivate) 523bf215546Sopenharmony_ci{ 524bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 525bf215546Sopenharmony_ci int internal_stride; 526bf215546Sopenharmony_ci struct gbm_dri_bo *bo; 527bf215546Sopenharmony_ci uint32_t bpp; 528bf215546Sopenharmony_ci int x_bytes, width_bytes; 529bf215546Sopenharmony_ci char *src, *dst; 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci if (op != __DRI_SWRAST_IMAGE_OP_DRAW && 532bf215546Sopenharmony_ci op != __DRI_SWRAST_IMAGE_OP_SWAP) 533bf215546Sopenharmony_ci return; 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci if (get_swrast_front_bo(dri2_surf) < 0) 536bf215546Sopenharmony_ci return; 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci bo = gbm_dri_bo(dri2_surf->current->bo); 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci bpp = gbm_bo_get_bpp(&bo->base); 541bf215546Sopenharmony_ci if (bpp == 0) 542bf215546Sopenharmony_ci return; 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_ci x_bytes = x * (bpp >> 3); 545bf215546Sopenharmony_ci width_bytes = width * (bpp >> 3); 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci if (gbm_dri_bo_map_dumb(bo) == NULL) 548bf215546Sopenharmony_ci return; 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci internal_stride = bo->base.v0.stride; 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci dst = bo->map + x_bytes + (y * internal_stride); 553bf215546Sopenharmony_ci src = data; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci for (int i = 0; i < height; i++) { 556bf215546Sopenharmony_ci memcpy(dst, src, width_bytes); 557bf215546Sopenharmony_ci dst += internal_stride; 558bf215546Sopenharmony_ci src += stride; 559bf215546Sopenharmony_ci } 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci gbm_dri_bo_unmap_dumb(bo); 562bf215546Sopenharmony_ci} 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_cistatic void 565bf215546Sopenharmony_ciswrast_get_image(__DRIdrawable *driDrawable, 566bf215546Sopenharmony_ci int x, 567bf215546Sopenharmony_ci int y, 568bf215546Sopenharmony_ci int width, 569bf215546Sopenharmony_ci int height, 570bf215546Sopenharmony_ci char *data, 571bf215546Sopenharmony_ci void *loaderPrivate) 572bf215546Sopenharmony_ci{ 573bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 574bf215546Sopenharmony_ci int internal_stride, stride; 575bf215546Sopenharmony_ci struct gbm_dri_bo *bo; 576bf215546Sopenharmony_ci uint32_t bpp; 577bf215546Sopenharmony_ci int x_bytes, width_bytes; 578bf215546Sopenharmony_ci char *src, *dst; 579bf215546Sopenharmony_ci 580bf215546Sopenharmony_ci if (get_swrast_front_bo(dri2_surf) < 0) 581bf215546Sopenharmony_ci return; 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci bo = gbm_dri_bo(dri2_surf->current->bo); 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci bpp = gbm_bo_get_bpp(&bo->base); 586bf215546Sopenharmony_ci if (bpp == 0) 587bf215546Sopenharmony_ci return; 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_ci x_bytes = x * (bpp >> 3); 590bf215546Sopenharmony_ci width_bytes = width * (bpp >> 3); 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci internal_stride = bo->base.v0.stride; 593bf215546Sopenharmony_ci stride = width_bytes; 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci if (gbm_dri_bo_map_dumb(bo) == NULL) 596bf215546Sopenharmony_ci return; 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci dst = data; 599bf215546Sopenharmony_ci src = bo->map + x_bytes + (y * internal_stride); 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci for (int i = 0; i < height; i++) { 602bf215546Sopenharmony_ci memcpy(dst, src, width_bytes); 603bf215546Sopenharmony_ci dst += stride; 604bf215546Sopenharmony_ci src += internal_stride; 605bf215546Sopenharmony_ci } 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci gbm_dri_bo_unmap_dumb(bo); 608bf215546Sopenharmony_ci} 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_cistatic EGLBoolean 611bf215546Sopenharmony_cidrm_add_configs_for_visuals(_EGLDisplay *disp) 612bf215546Sopenharmony_ci{ 613bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 614bf215546Sopenharmony_ci const struct gbm_dri_visual *visuals = dri2_dpy->gbm_dri->visual_table; 615bf215546Sopenharmony_ci int num_visuals = dri2_dpy->gbm_dri->num_visuals; 616bf215546Sopenharmony_ci unsigned int format_count[num_visuals]; 617bf215546Sopenharmony_ci unsigned int config_count = 0; 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci memset(format_count, 0, num_visuals * sizeof(unsigned int)); 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) { 622bf215546Sopenharmony_ci const __DRIconfig *config = dri2_dpy->driver_configs[i]; 623bf215546Sopenharmony_ci int shifts[4]; 624bf215546Sopenharmony_ci unsigned int sizes[4]; 625bf215546Sopenharmony_ci bool is_float; 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes); 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci dri2_get_render_type_float(dri2_dpy->core, config, &is_float); 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci for (unsigned j = 0; j < num_visuals; j++) { 632bf215546Sopenharmony_ci struct dri2_egl_config *dri2_conf; 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci if (visuals[j].rgba_shifts.red != shifts[0] || 635bf215546Sopenharmony_ci visuals[j].rgba_shifts.green != shifts[1] || 636bf215546Sopenharmony_ci visuals[j].rgba_shifts.blue != shifts[2] || 637bf215546Sopenharmony_ci visuals[j].rgba_shifts.alpha != shifts[3] || 638bf215546Sopenharmony_ci visuals[j].rgba_sizes.red != sizes[0] || 639bf215546Sopenharmony_ci visuals[j].rgba_sizes.green != sizes[1] || 640bf215546Sopenharmony_ci visuals[j].rgba_sizes.blue != sizes[2] || 641bf215546Sopenharmony_ci visuals[j].rgba_sizes.alpha != sizes[3] || 642bf215546Sopenharmony_ci visuals[j].is_float != is_float) 643bf215546Sopenharmony_ci continue; 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_ci const EGLint attr_list[] = { 646bf215546Sopenharmony_ci EGL_NATIVE_VISUAL_ID, visuals[j].gbm_format, 647bf215546Sopenharmony_ci EGL_NONE, 648bf215546Sopenharmony_ci }; 649bf215546Sopenharmony_ci 650bf215546Sopenharmony_ci dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i], 651bf215546Sopenharmony_ci config_count + 1, EGL_WINDOW_BIT, attr_list, NULL, NULL); 652bf215546Sopenharmony_ci if (dri2_conf) { 653bf215546Sopenharmony_ci if (dri2_conf->base.ConfigID == config_count + 1) 654bf215546Sopenharmony_ci config_count++; 655bf215546Sopenharmony_ci format_count[j]++; 656bf215546Sopenharmony_ci } 657bf215546Sopenharmony_ci } 658bf215546Sopenharmony_ci } 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { 661bf215546Sopenharmony_ci if (!format_count[i]) { 662bf215546Sopenharmony_ci struct gbm_format_name_desc desc; 663bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", 664bf215546Sopenharmony_ci gbm_format_get_name(visuals[i].gbm_format, &desc)); 665bf215546Sopenharmony_ci } 666bf215546Sopenharmony_ci } 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci return (config_count != 0); 669bf215546Sopenharmony_ci} 670bf215546Sopenharmony_ci 671bf215546Sopenharmony_cistatic const struct dri2_egl_display_vtbl dri2_drm_display_vtbl = { 672bf215546Sopenharmony_ci .authenticate = dri2_drm_authenticate, 673bf215546Sopenharmony_ci .create_window_surface = dri2_drm_create_window_surface, 674bf215546Sopenharmony_ci .create_pixmap_surface = dri2_drm_create_pixmap_surface, 675bf215546Sopenharmony_ci .destroy_surface = dri2_drm_destroy_surface, 676bf215546Sopenharmony_ci .create_image = dri2_drm_create_image_khr, 677bf215546Sopenharmony_ci .swap_buffers = dri2_drm_swap_buffers, 678bf215546Sopenharmony_ci .query_buffer_age = dri2_drm_query_buffer_age, 679bf215546Sopenharmony_ci .get_dri_drawable = dri2_surface_get_dri_drawable, 680bf215546Sopenharmony_ci}; 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_ciEGLBoolean 683bf215546Sopenharmony_cidri2_initialize_drm(_EGLDisplay *disp) 684bf215546Sopenharmony_ci{ 685bf215546Sopenharmony_ci _EGLDevice *dev; 686bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy; 687bf215546Sopenharmony_ci struct gbm_device *gbm; 688bf215546Sopenharmony_ci const char *err; 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ci dri2_dpy = calloc(1, sizeof *dri2_dpy); 691bf215546Sopenharmony_ci if (!dri2_dpy) 692bf215546Sopenharmony_ci return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_ci dri2_dpy->fd = -1; 695bf215546Sopenharmony_ci disp->DriverData = (void *) dri2_dpy; 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ci gbm = disp->PlatformDisplay; 698bf215546Sopenharmony_ci if (gbm == NULL) { 699bf215546Sopenharmony_ci char buf[64]; 700bf215546Sopenharmony_ci int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0); 701bf215546Sopenharmony_ci if (n != -1 && n < sizeof(buf)) 702bf215546Sopenharmony_ci dri2_dpy->fd = loader_open_device(buf); 703bf215546Sopenharmony_ci gbm = gbm_create_device(dri2_dpy->fd); 704bf215546Sopenharmony_ci if (gbm == NULL) { 705bf215546Sopenharmony_ci err = "DRI2: failed to create gbm device"; 706bf215546Sopenharmony_ci goto cleanup; 707bf215546Sopenharmony_ci } 708bf215546Sopenharmony_ci dri2_dpy->own_device = true; 709bf215546Sopenharmony_ci } else { 710bf215546Sopenharmony_ci dri2_dpy->fd = os_dupfd_cloexec(gbm_device_get_fd(gbm)); 711bf215546Sopenharmony_ci if (dri2_dpy->fd < 0) { 712bf215546Sopenharmony_ci err = "DRI2: failed to fcntl() existing gbm device"; 713bf215546Sopenharmony_ci goto cleanup; 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci } 716bf215546Sopenharmony_ci dri2_dpy->gbm_dri = gbm_dri_device(gbm); 717bf215546Sopenharmony_ci 718bf215546Sopenharmony_ci if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) { 719bf215546Sopenharmony_ci err = "DRI2: gbm device using incorrect/incompatible backend"; 720bf215546Sopenharmony_ci goto cleanup; 721bf215546Sopenharmony_ci } 722bf215546Sopenharmony_ci 723bf215546Sopenharmony_ci dev = _eglAddDevice(dri2_dpy->fd, dri2_dpy->gbm_dri->software); 724bf215546Sopenharmony_ci if (!dev) { 725bf215546Sopenharmony_ci err = "DRI2: failed to find EGLDevice"; 726bf215546Sopenharmony_ci goto cleanup; 727bf215546Sopenharmony_ci } 728bf215546Sopenharmony_ci 729bf215546Sopenharmony_ci disp->Device = dev; 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_ci dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->driver_name); 732bf215546Sopenharmony_ci dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER; 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci /* render nodes cannot use Gem names, and thus do not support 735bf215546Sopenharmony_ci * the __DRI_DRI2_LOADER extension */ 736bf215546Sopenharmony_ci if (!dri2_dpy->is_render_node) { 737bf215546Sopenharmony_ci if (!dri2_load_driver(disp)) { 738bf215546Sopenharmony_ci err = "DRI2: failed to load driver"; 739bf215546Sopenharmony_ci goto cleanup; 740bf215546Sopenharmony_ci } 741bf215546Sopenharmony_ci } else { 742bf215546Sopenharmony_ci if (!dri2_load_driver_dri3(disp)) { 743bf215546Sopenharmony_ci err = "DRI3: failed to load driver"; 744bf215546Sopenharmony_ci goto cleanup; 745bf215546Sopenharmony_ci } 746bf215546Sopenharmony_ci } 747bf215546Sopenharmony_ci 748bf215546Sopenharmony_ci dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen; 749bf215546Sopenharmony_ci dri2_dpy->core = dri2_dpy->gbm_dri->core; 750bf215546Sopenharmony_ci dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2; 751bf215546Sopenharmony_ci dri2_dpy->swrast = dri2_dpy->gbm_dri->swrast; 752bf215546Sopenharmony_ci dri2_dpy->kopper = dri2_dpy->gbm_dri->kopper; 753bf215546Sopenharmony_ci dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs; 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image; 756bf215546Sopenharmony_ci dri2_dpy->gbm_dri->validate_image = dri2_validate_egl_image; 757bf215546Sopenharmony_ci dri2_dpy->gbm_dri->lookup_image_validated = dri2_lookup_egl_image_validated; 758bf215546Sopenharmony_ci dri2_dpy->gbm_dri->lookup_user_data = disp; 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_ci dri2_dpy->gbm_dri->get_buffers = dri2_drm_get_buffers; 761bf215546Sopenharmony_ci dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer; 762bf215546Sopenharmony_ci dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format; 763bf215546Sopenharmony_ci dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers; 764bf215546Sopenharmony_ci dri2_dpy->gbm_dri->swrast_put_image2 = swrast_put_image2; 765bf215546Sopenharmony_ci dri2_dpy->gbm_dri->swrast_get_image = swrast_get_image; 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_ci dri2_dpy->gbm_dri->base.v0.surface_lock_front_buffer = lock_front_buffer; 768bf215546Sopenharmony_ci dri2_dpy->gbm_dri->base.v0.surface_release_buffer = release_buffer; 769bf215546Sopenharmony_ci dri2_dpy->gbm_dri->base.v0.surface_has_free_buffers = has_free_buffers; 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci if (!dri2_setup_extensions(disp)) { 772bf215546Sopenharmony_ci err = "DRI2: failed to find required DRI extensions"; 773bf215546Sopenharmony_ci goto cleanup; 774bf215546Sopenharmony_ci } 775bf215546Sopenharmony_ci 776bf215546Sopenharmony_ci dri2_setup_screen(disp); 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci if (!drm_add_configs_for_visuals(disp)) { 779bf215546Sopenharmony_ci err = "DRI2: failed to add configs"; 780bf215546Sopenharmony_ci goto cleanup; 781bf215546Sopenharmony_ci } 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_ci disp->Extensions.KHR_image_pixmap = EGL_TRUE; 784bf215546Sopenharmony_ci if (dri2_dpy->dri2) 785bf215546Sopenharmony_ci disp->Extensions.EXT_buffer_age = EGL_TRUE; 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci#ifdef HAVE_WAYLAND_PLATFORM 788bf215546Sopenharmony_ci dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd); 789bf215546Sopenharmony_ci#endif 790bf215546Sopenharmony_ci dri2_set_WL_bind_wayland_display(disp); 791bf215546Sopenharmony_ci 792bf215546Sopenharmony_ci /* Fill vtbl last to prevent accidentally calling virtual function during 793bf215546Sopenharmony_ci * initialization. 794bf215546Sopenharmony_ci */ 795bf215546Sopenharmony_ci dri2_dpy->vtbl = &dri2_drm_display_vtbl; 796bf215546Sopenharmony_ci 797bf215546Sopenharmony_ci return EGL_TRUE; 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_cicleanup: 800bf215546Sopenharmony_ci dri2_display_destroy(disp); 801bf215546Sopenharmony_ci return _eglError(EGL_NOT_INITIALIZED, err); 802bf215546Sopenharmony_ci} 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_civoid 805bf215546Sopenharmony_cidri2_teardown_drm(struct dri2_egl_display *dri2_dpy) 806bf215546Sopenharmony_ci{ 807bf215546Sopenharmony_ci if (dri2_dpy->own_device) 808bf215546Sopenharmony_ci gbm_device_destroy(&dri2_dpy->gbm_dri->base); 809bf215546Sopenharmony_ci} 810