static _EGLSurface * droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, _EGLConfig *conf, void *native_window, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); struct dri2_egl_surface *dri2_surf; struct ANativeWindow *window = native_window; const __DRIconfig *config; dri2_surf = calloc(1, sizeof *dri2_surf); if (!dri2_surf) { _eglError(EGL_BAD_ALLOC, "droid_create_surface"); return NULL; } if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) goto cleanup_surface; if (type == EGL_WINDOW_BIT) { int format; if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); goto cleanup_surface; } if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) { _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface"); goto cleanup_surface; } if (format != dri2_conf->base.NativeVisualID) { _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x", format, dri2_conf->base.NativeVisualID); } window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width); window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height); } config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT, dri2_surf->base.GLColorspace); if (!config) goto cleanup_surface; dri2_surf->dri_drawable = (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config, dri2_surf); if (dri2_surf->dri_drawable == NULL) { _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); goto cleanup_surface; } if (window) { window->common.incRef(&window->common); dri2_surf->window = window; } return &dri2_surf->base; cleanup_surface: free(dri2_surf); return NULL; }
EGLBoolean dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy) { struct dri2_egl_display *dri2_dpy; const char *err; _eglSetLogProc(droid_log); loader_set_logger(_eglLog); dri2_dpy = calloc(1, sizeof(*dri2_dpy)); if (!dri2_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); dpy->DriverData = (void *) dri2_dpy; dri2_dpy->fd = droid_open_device(); if (dri2_dpy->fd < 0) { err = "DRI2: failed to open device"; goto cleanup_display; } dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0); if (dri2_dpy->driver_name == NULL) { err = "DRI2: failed to get driver name"; goto cleanup_device; } if (!dri2_load_driver(dpy)) { err = "DRI2: failed to load driver"; goto cleanup_driver_name; } dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER; /* render nodes cannot use Gem names, and thus do not support * the __DRI_DRI2_LOADER extension */ if (!dri2_dpy->is_render_node) { dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER; dri2_dpy->dri2_loader_extension.base.version = 3; dri2_dpy->dri2_loader_extension.getBuffers = NULL; dri2_dpy->dri2_loader_extension.flushFrontBuffer = droid_flush_front_buffer; dri2_dpy->dri2_loader_extension.getBuffersWithFormat = droid_get_buffers_with_format; dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base; } else { dri2_dpy->extensions[0] = &droid_image_loader_extension.base; } dri2_dpy->extensions[1] = &use_invalidate.base; dri2_dpy->extensions[2] = &image_lookup_extension.base; dri2_dpy->extensions[3] = NULL; if (!dri2_create_screen(dpy)) { err = "DRI2: failed to create screen"; goto cleanup_driver; } if (!droid_add_configs_for_visuals(drv, dpy)) { err = "DRI2: failed to add configs"; goto cleanup_screen; } dpy->Extensions.ANDROID_framebuffer_target = EGL_TRUE; dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; dpy->Extensions.ANDROID_recordable = EGL_TRUE; dpy->Extensions.KHR_image_base = EGL_TRUE; /* Fill vtbl last to prevent accidentally calling virtual function during * initialization. */ dri2_dpy->vtbl = &droid_display_vtbl; return EGL_TRUE; cleanup_screen: dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); cleanup_driver: dlclose(dri2_dpy->driver); cleanup_driver_name: free(dri2_dpy->driver_name); cleanup_device: close(dri2_dpy->fd); cleanup_display: free(dri2_dpy); return _eglError(EGL_NOT_INITIALIZED, err); }
/** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ static _EGLSurface * dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, _EGLConfig *conf, void *native_surface, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); struct dri2_egl_surface *dri2_surf; xcb_get_geometry_cookie_t cookie; xcb_get_geometry_reply_t *reply; xcb_generic_error_t *error; const __DRIconfig *config; (void) drv; dri2_surf = malloc(sizeof *dri2_surf); if (!dri2_surf) { _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); return NULL; } if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, false, native_surface)) goto cleanup_surf; dri2_surf->region = XCB_NONE; if (type == EGL_PBUFFER_BIT) { dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, dri2_surf->drawable, dri2_dpy->screen->root, dri2_surf->base.Width, dri2_surf->base.Height); } else { STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface)); dri2_surf->drawable = (uintptr_t) native_surface; } config = dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace); if (!config) { _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); goto cleanup_pixmap; } if (dri2_dpy->dri2) { dri2_surf->dri_drawable = dri2_dpy->dri2->createNewDrawable(dri2_dpy->dri_screen, config, dri2_surf); } else { assert(dri2_dpy->swrast); dri2_surf->dri_drawable = dri2_dpy->swrast->createNewDrawable(dri2_dpy->dri_screen, config, dri2_surf); } if (dri2_surf->dri_drawable == NULL) { _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); goto cleanup_pixmap; } if (type != EGL_PBUFFER_BIT) { cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); if (error != NULL) { if (error->error_code == BadAlloc) _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); else if (type == EGL_WINDOW_BIT) _eglError(EGL_BAD_NATIVE_WINDOW, "xcb_get_geometry"); else _eglError(EGL_BAD_NATIVE_PIXMAP, "xcb_get_geometry"); free(error); goto cleanup_dri_drawable; } else if (reply == NULL) { _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); goto cleanup_dri_drawable; } dri2_surf->base.Width = reply->width; dri2_surf->base.Height = reply->height; dri2_surf->depth = reply->depth; free(reply); } if (dri2_dpy->dri2) { xcb_void_cookie_t cookie; int conn_error; cookie = xcb_dri2_create_drawable_checked(dri2_dpy->conn, dri2_surf->drawable); error = xcb_request_check(dri2_dpy->conn, cookie); conn_error = xcb_connection_has_error(dri2_dpy->conn); if (conn_error || error != NULL) { if (type == EGL_PBUFFER_BIT || conn_error || error->error_code == BadAlloc) _eglError(EGL_BAD_ALLOC, "xcb_dri2_create_drawable_checked"); else if (type == EGL_WINDOW_BIT) _eglError(EGL_BAD_NATIVE_WINDOW, "xcb_dri2_create_drawable_checked"); else _eglError(EGL_BAD_NATIVE_PIXMAP, "xcb_dri2_create_drawable_checked"); free(error); goto cleanup_dri_drawable; } } else { if (type == EGL_PBUFFER_BIT) { dri2_surf->depth = _eglGetConfigKey(conf, EGL_BUFFER_SIZE); } swrastCreateDrawable(dri2_dpy, dri2_surf); } /* we always copy the back buffer to front */ dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE; return &dri2_surf->base; cleanup_dri_drawable: dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); cleanup_pixmap: if (type == EGL_PBUFFER_BIT) xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable); cleanup_surf: free(dri2_surf); return NULL; }
/** * Drivers will typically call this to do the error checking and * update the various flags. * Then, the driver will do its device-dependent Make-Current stuff. */ EGLBoolean _eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) { _EGLThreadInfo *t = _eglGetCurrentThread(); _EGLContext *oldContext = NULL; _EGLSurface *oldDrawSurface = NULL; _EGLSurface *oldReadSurface = NULL; EGLint apiIndex; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); if (ctx) { /* error checking */ if (ctx->Binding && ctx->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); if (draw == NULL || read == NULL) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); if (draw->Config != ctx->Config || read->Config != ctx->Config) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); if ((draw->Binding && draw->Binding->Binding != t) || (read->Binding && read->Binding->Binding != t)) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); #ifdef EGL_VERSION_1_4 /* OpenGL and OpenGL ES are conflicting */ switch (ctx->ClientAPI) { case EGL_OPENGL_ES_API: if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); break; case EGL_OPENGL_API: if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)]) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); break; default: break; } #endif apiIndex = _eglConvertApiToIndex(ctx->ClientAPI); } else { if (draw != NULL || read != NULL) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); apiIndex = t->CurrentAPIIndex; } oldContext = t->CurrentContexts[apiIndex]; if (oldContext) { oldDrawSurface = oldContext->DrawSurface; oldReadSurface = oldContext->ReadSurface; assert(oldDrawSurface); assert(oldReadSurface); /* break old bindings */ t->CurrentContexts[apiIndex] = NULL; oldContext->Binding = NULL; oldContext->DrawSurface = NULL; oldContext->ReadSurface = NULL; oldDrawSurface->Binding = NULL; oldReadSurface->Binding = NULL; /* * check if the old context or surfaces need to be deleted */ if (!_eglIsSurfaceLinked(oldDrawSurface)) { assert(draw != oldDrawSurface && read != oldDrawSurface); drv->API.DestroySurface(drv, dpy, oldDrawSurface); } if (oldReadSurface != oldDrawSurface && !_eglIsSurfaceLinked(oldReadSurface)) { assert(draw != oldReadSurface && read != oldReadSurface); drv->API.DestroySurface(drv, dpy, oldReadSurface); } if (!_eglIsContextLinked(oldContext)) { assert(ctx != oldContext); drv->API.DestroyContext(drv, dpy, oldContext); } } /* build new bindings */ if (ctx) { t->CurrentContexts[apiIndex] = ctx; ctx->Binding = t; ctx->DrawSurface = draw; ctx->ReadSurface = read; draw->Binding = ctx; read->Binding = ctx; } return EGL_TRUE; }
static _EGLImage * dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, EGLClientBuffer buffer, const EGLint *attr_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_image *dri2_img; unsigned int attachments[1]; xcb_drawable_t drawable; xcb_dri2_get_buffers_cookie_t buffers_cookie; xcb_dri2_get_buffers_reply_t *buffers_reply; xcb_dri2_dri2_buffer_t *buffers; xcb_get_geometry_cookie_t geometry_cookie; xcb_get_geometry_reply_t *geometry_reply; xcb_generic_error_t *error; int stride, format; (void) ctx; drawable = (xcb_drawable_t) (uintptr_t) buffer; xcb_dri2_create_drawable (dri2_dpy->conn, drawable); attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT; buffers_cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, drawable, 1, 1, attachments); geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable); buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, buffers_cookie, NULL); if (buffers_reply == NULL) return NULL; buffers = xcb_dri2_get_buffers_buffers (buffers_reply); if (buffers == NULL) { return NULL; } geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn, geometry_cookie, &error); if (geometry_reply == NULL || error != NULL) { _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); free(error); free(buffers_reply); return NULL; } format = dri2_format_for_depth(dri2_dpy, geometry_reply->depth); if (format == __DRI_IMAGE_FORMAT_NONE) { _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr: unsupported pixmap depth"); free(buffers_reply); free(geometry_reply); return NULL; } dri2_img = malloc(sizeof *dri2_img); if (!dri2_img) { free(buffers_reply); free(geometry_reply); _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); return EGL_NO_IMAGE_KHR; } _eglInitImage(&dri2_img->base, disp); stride = buffers[0].pitch / buffers[0].cpp; dri2_img->dri_image = dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, buffers_reply->width, buffers_reply->height, format, buffers[0].name, stride, dri2_img); free(buffers_reply); free(geometry_reply); return &dri2_img->base; }
static EGLBoolean dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) { _EGLDevice *dev; struct dri2_egl_display *dri2_dpy; dri2_dpy = calloc(1, sizeof *dri2_dpy); if (!dri2_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); dri2_dpy->fd = -1; if (!dri2_get_xcb_connection(drv, disp, dri2_dpy)) goto cleanup; if (!dri2_x11_connect(dri2_dpy)) goto cleanup; dev = _eglAddDevice(dri2_dpy->fd, false); if (!dev) { _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice"); goto cleanup; } disp->Device = dev; if (!dri2_load_driver(disp)) goto cleanup; if (dri2_dpy->dri2_minor >= 1) dri2_dpy->loader_extensions = dri2_loader_extensions; else dri2_dpy->loader_extensions = dri2_loader_extensions_old; dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2); dri2_dpy->invalidate_available = (dri2_dpy->dri2_minor >= 3); if (!dri2_create_screen(disp)) goto cleanup; if (!dri2_setup_extensions(disp)) goto cleanup; dri2_setup_screen(disp); dri2_x11_setup_swap_interval(disp); disp->Extensions.KHR_image_pixmap = EGL_TRUE; disp->Extensions.NOK_swap_region = EGL_TRUE; disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; disp->Extensions.NV_post_sub_buffer = EGL_TRUE; disp->Extensions.CHROMIUM_sync_control = EGL_TRUE; dri2_set_WL_bind_wayland_display(drv, disp); if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true)) goto cleanup; /* Fill vtbl last to prevent accidentally calling virtual function during * initialization. */ dri2_dpy->vtbl = &dri2_x11_display_vtbl; _eglLog(_EGL_INFO, "Using DRI2"); return EGL_TRUE; cleanup: dri2_display_destroy(disp); return EGL_FALSE; }
static _EGLSurface * dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, _EGLConfig *conf, EGLNativeWindowType window, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); struct dri2_egl_surface *dri2_surf; struct gbm_dri_surface *surf; struct gbm_bo *bo; _EGLImage *img; EGLint attr[10]; (void) drv; dri2_surf = calloc(1, sizeof *dri2_surf); if (!dri2_surf) { _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); return NULL; } if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) goto cleanup_surf; switch (type) { case EGL_WINDOW_BIT: if (!window) return NULL; surf = gbm_dri_surface((struct gbm_surface *) window); dri2_surf->gbm_surf = surf; dri2_surf->base.Width = surf->base.width; dri2_surf->base.Height = surf->base.height; surf->dri_private = dri2_surf; break; default: goto cleanup_surf; } attr[0] = EGL_WIDTH; attr[1] = surf->base.width; attr[2] = EGL_HEIGHT; attr[3] = surf->base.height; attr[4] = EGL_DRM_BUFFER_FORMAT_MESA; attr[5] = EGL_DRM_BUFFER_FORMAT_ARGB32_MESA; attr[6] = EGL_DRM_BUFFER_USE_MESA; attr[7] = EGL_DRM_BUFFER_USE_SHARE_MESA; attr[8] = EGL_NONE; img = drv->API.CreateDRMImageMESA(drv, disp, attr); dri2_surf->egl_front = img; dri2_surf->khr_front = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; bo = gbm_bo_import(&dri2_dpy->gbm_dri->base.base, GBM_BO_IMPORT_EGL_IMAGE, dri2_surf->khr_front, 0); if( bo == NULL){ _eglError(EGL_BAD_ALLOC, "gbm_bo_create front buffer"); goto cleanup_surf; } dri2_surf->color_buffers[1].bo = bo; img = drv->API.CreateDRMImageMESA(drv, disp, attr); dri2_surf->egl_back = img; dri2_surf->khr_back = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; bo = gbm_bo_import(&dri2_dpy->gbm_dri->base.base, GBM_BO_IMPORT_EGL_IMAGE, dri2_surf->khr_back, 0); if( bo == NULL){ _eglError(EGL_BAD_ALLOC, "gbm_bo_create back buffer"); goto cleanup_surf; } dri2_surf->color_buffers[2].bo = bo; dri2_surf->dri_drawable = (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, dri2_conf->dri_double_config, dri2_surf->gbm_surf); if (dri2_surf->dri_drawable == NULL) { _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); goto cleanup_surf; } return &dri2_surf->base; cleanup_surf: free(dri2_surf); return NULL; }
/** * Return true if the given context and surfaces can be made current. */ static EGLBoolean _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) { _EGLThreadInfo *t = _eglGetCurrentThread(); _EGLDisplay *dpy; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); /* this is easy */ if (!ctx) { if (draw || read) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); return EGL_TRUE; } dpy = ctx->Resource.Display; if (!dpy->Extensions.KHR_surfaceless_context && (draw == NULL || read == NULL)) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); /* * The spec says * * "If ctx is current to some other thread, or if either draw or read are * bound to contexts in another thread, an EGL_BAD_ACCESS error is * generated." * * and * * "at most one context may be bound to a particular surface at a given * time" */ if (ctx->Binding && ctx->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { if (draw->CurrentContext->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); } if (read && read->CurrentContext && read->CurrentContext != ctx) { if (read->CurrentContext->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); } /* If the context has a config then it must match that of the two * surfaces */ if (ctx->Config) { if ((draw && draw->Config != ctx->Config) || (read && read->Config != ctx->Config)) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); } else { /* Otherwise we must be using the EGL_KHR_no_config_context * extension */ assert(dpy->Extensions.KHR_no_config_context); /* The extension doesn't permit binding draw and read buffers with * differing contexts */ if (draw && read && draw->Config != read->Config) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); } return EGL_TRUE; }
static EGLBoolean dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); __DRIbuffer buffer; static bitmap_t bm; int i; if (dri2_surf->base.Type == EGL_WINDOW_BIT) { if (dri2_surf->current) _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers"); for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) if (dri2_surf->color_buffers[i].age > 0) dri2_surf->color_buffers[i].age++; #if 0 if ( (dri2_surf->back != NULL) && (dri2_surf->back->bo != NULL)) { struct gbm_dri_bo *bo; bo = (struct gbm_dri_bo *)dri2_surf->back->bo; if(bm.width == 0) { // printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n", // __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width, // bo->base.base.height, (int)bo->base.base.stride, // bo->base.base.format); bm.width = bo->base.base.width; bm.height = bo->base.base.height; bm.pitch = (int)bo->base.base.stride; bm.max_width = bo->base.base.width; bm.max_height = bo->base.base.height; bm.flags = HW_TEX_BLIT; if( blit_bitmap_from_handle(&bm, bo->base.base.handle.s32)) { printf("sna_bitmap_from_handle failed\n"); } } if( bm.handle != 0) { // printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n", // __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width, // bo->base.base.height, (int)bo->base.base.stride, // bo->base.base.format); blit_set_bo_handle(&bm, bo->base.base.handle.s32); blit_blit_tex(&bm, 0, 0, 5, 20, bm.width, bm.height, 0, 0); } } #endif dri2_surf->current = dri2_surf->back; dri2_surf->current->age = 1; dri2_surf->back = NULL; } (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); return EGL_TRUE; }
EGLBoolean dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy; struct gbm_device *gbm; void *lib; int fd = -1; int i; dri2_dpy = calloc(1, sizeof *dri2_dpy); if (!dri2_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); disp->DriverData = (void *) dri2_dpy; gbm = disp->PlatformDisplay; if (gbm == NULL) { fd = get_service("DISPLAY"); dri2_dpy->own_device = 1; gbm = gbm_create_device(fd); if (gbm == NULL) return EGL_FALSE; } if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) { free(dri2_dpy); return EGL_FALSE; } dri2_dpy->gbm_dri = gbm_dri_device(gbm); if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) { free(dri2_dpy); return EGL_FALSE; } #if 0 lib = load_library("intel-sna.drv"); if(lib) { blit_bitmap_from_handle = get_proc_address(lib,"sna_bitmap_from_handle"); blit_set_bo_handle = get_proc_address(lib,"sna_set_bo_handle"); blit_blit_tex = get_proc_address(lib,"sna_blit_tex"); } else { lib = load_library("intel-uxa.drv"); if(lib) { blit_bitmap_from_handle = get_proc_address(lib,"uxa_bitmap_from_handle"); blit_set_bo_handle = get_proc_address(lib,"uxa_set_bo_handle"); blit_blit_tex = get_proc_address(lib,"uxa_blit_tex"); } else return EGL_FALSE; } #endif dri2_dpy->fd = fd; dri2_dpy->device_name = strdup("drm device"); //dri2_get_device_name_for_fd(dri2_dpy->fd); dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name; dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen; dri2_dpy->core = dri2_dpy->gbm_dri->core; dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2; dri2_dpy->image = dri2_dpy->gbm_dri->image; dri2_dpy->flush = dri2_dpy->gbm_dri->flush; dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs; dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image; dri2_dpy->gbm_dri->lookup_user_data = disp; dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers; dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer; dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format; dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer; dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer; dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers; dri2_setup_screen(disp); for (i = 0; dri2_dpy->driver_configs[i]; i++) dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, EGL_WINDOW_BIT, NULL, NULL); drv->API.CreateWindowSurface = dri2_create_window_surface; drv->API.DestroySurface = dri2_destroy_surface; drv->API.SwapBuffers = dri2_swap_buffers; drv->API.CreateImageKHR = dri2_drm_create_image_khr; drv->API.QueryBufferAge = dri2_query_buffer_age; drv->API.GetImageFB = dri2_get_fb_image; disp->Extensions.EXT_buffer_age = EGL_TRUE; #ifdef HAVE_WAYLAND_PLATFORM disp->Extensions.WL_bind_wayland_display = EGL_TRUE; #endif // dri2_dpy->authenticate = dri2_drm_authenticate; /* we're supporting EGL 1.4 */ disp->VersionMajor = 1; disp->VersionMinor = 4; return EGL_TRUE; }
/** * Called via eglInitialize(), xdri_dpy->API.Initialize(). */ static EGLBoolean xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, EGLint *minor, EGLint *major) { struct xdri_egl_display *xdri_dpy; __GLXdisplayPrivate *dpyPriv; __GLXDRIdisplay *driDisplay; __GLXscreenConfigs *psc; EGLint first_id = 1; int scr; xdri_dpy = CALLOC_STRUCT(xdri_egl_display); if (!xdri_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); xdri_dpy->dpy = (Display *) dpy->NativeDisplay; if (!xdri_dpy->dpy) { xdri_dpy->dpy = XOpenDisplay(NULL); if (!xdri_dpy->dpy) { free(xdri_dpy); return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } } dpyPriv = __glXInitialize(xdri_dpy->dpy); if (!dpyPriv) { _eglLog(_EGL_WARNING, "failed to create GLX display"); free(xdri_dpy); return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } driDisplay = __driCreateDisplay(dpyPriv, NULL); if (!driDisplay) { _eglLog(_EGL_WARNING, "failed to create DRI display"); free(xdri_dpy); return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } scr = DefaultScreen(xdri_dpy->dpy); psc = &dpyPriv->screenConfigs[scr]; xdri_dpy->dpyPriv = dpyPriv; xdri_dpy->driDisplay = driDisplay; xdri_dpy->psc = psc; xdri_dpy->scr = scr; psc->driScreen = driDisplay->createScreen(psc, scr, dpyPriv); if (!psc->driScreen) { _eglLog(_EGL_WARNING, "failed to create DRI screen #%d", scr); free(xdri_dpy); return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } /* add visuals and fbconfigs */ first_id = create_configs(dpy, psc->visuals, first_id); create_configs(dpy, psc->configs, first_id); dpy->DriverData = xdri_dpy; dpy->ClientAPIsMask = (EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT); /* we're supporting EGL 1.4 */ *minor = 1; *major = 4; return EGL_TRUE; }
/** * Parse the attrib_list to fill in the fields of the given _eglMode * Return EGL_FALSE if any errors, EGL_TRUE otherwise. */ static EGLBoolean _eglParseModeAttribs(_EGLMode *mode, const EGLint *attrib_list) { EGLint i; /* init all attribs to EGL_DONT_CARE */ mode->Handle = EGL_DONT_CARE; mode->Width = EGL_DONT_CARE; mode->Height = EGL_DONT_CARE; mode->RefreshRate = EGL_DONT_CARE; mode->Optimal = EGL_DONT_CARE; mode->Interlaced = EGL_DONT_CARE; mode->Name = NULL; for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { switch (attrib_list[i]) { case EGL_MODE_ID_MESA: mode->Handle = attrib_list[++i]; if (mode->Handle <= 0) { _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(handle)"); return EGL_FALSE; } break; case EGL_WIDTH: mode->Width = attrib_list[++i]; if (mode->Width <= 0) { _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(width)"); return EGL_FALSE; } break; case EGL_HEIGHT: mode->Height = attrib_list[++i]; if (mode->Height <= 0) { _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(height)"); return EGL_FALSE; } break; case EGL_REFRESH_RATE_MESA: mode->RefreshRate = attrib_list[++i]; if (mode->RefreshRate <= 0) { _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(refresh rate)"); return EGL_FALSE; } break; case EGL_INTERLACED_MESA: mode->Interlaced = attrib_list[++i]; if (mode->Interlaced != EGL_TRUE && mode->Interlaced != EGL_FALSE) { _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(interlaced)"); return EGL_FALSE; } break; case EGL_OPTIMAL_MESA: mode->Optimal = attrib_list[++i]; if (mode->Optimal != EGL_TRUE && mode->Optimal != EGL_FALSE) { _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(optimal)"); return EGL_FALSE; } break; default: _eglError(EGL_BAD_ATTRIBUTE, "eglChooseModeMESA"); return EGL_FALSE; } } return EGL_TRUE; }
static EGLBoolean egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); struct egl_g3d_display *gdpy; const struct native_platform *nplat; nplat = egl_g3d_get_platform(drv, dpy->Platform); if (!nplat) return EGL_FALSE; if (dpy->Options.TestOnly) return EGL_TRUE; gdpy = CALLOC_STRUCT(egl_g3d_display); if (!gdpy) { _eglError(EGL_BAD_ALLOC, "eglInitialize"); goto fail; } gdpy->loader = gdrv->loader; dpy->DriverData = gdpy; _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay); gdpy->native = nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback); if (!gdpy->native) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); goto fail; } gdpy->native->user_data = (void *) dpy; if (!gdpy->native->init_screen(gdpy->native)) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(failed to initialize screen)"); goto fail; } if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK) dpy->ClientAPIs |= EGL_OPENGL_BIT; if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK) dpy->ClientAPIs |= EGL_OPENGL_ES_BIT; if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK) dpy->ClientAPIs |= EGL_OPENGL_ES2_BIT; if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK) dpy->ClientAPIs |= EGL_OPENVG_BIT; gdpy->smapi = egl_g3d_create_st_manager(dpy); if (!gdpy->smapi) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(failed to create st manager)"); goto fail; } #ifdef EGL_MESA_screen_surface /* enable MESA_screen_surface before adding (and validating) configs */ if (gdpy->native->modeset) { dpy->Extensions.MESA_screen_surface = EGL_TRUE; egl_g3d_add_screens(drv, dpy); } #endif dpy->Extensions.KHR_image_base = EGL_TRUE; if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) dpy->Extensions.KHR_image_pixmap = EGL_TRUE; dpy->Extensions.KHR_reusable_sync = EGL_TRUE; dpy->Extensions.KHR_fence_sync = EGL_TRUE; dpy->Extensions.KHR_surfaceless_context = EGL_TRUE; if (dpy->Platform == _EGL_PLATFORM_DRM) { dpy->Extensions.MESA_drm_display = EGL_TRUE; if (gdpy->native->buffer) dpy->Extensions.MESA_drm_image = EGL_TRUE; } if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer) dpy->Extensions.MESA_drm_image = EGL_TRUE; #ifdef EGL_ANDROID_image_native_buffer if (dpy->Platform == _EGL_PLATFORM_ANDROID && gdpy->native->buffer) dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; #endif #ifdef EGL_WL_bind_wayland_display if (gdpy->native->wayland_bufmgr) dpy->Extensions.WL_bind_wayland_display = EGL_TRUE; #endif if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESENT_REGION) && gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER)) { #ifdef EGL_NOK_swap_region dpy->Extensions.NOK_swap_region = EGL_TRUE; #endif dpy->Extensions.NV_post_sub_buffer = EGL_TRUE; } if (egl_g3d_add_configs(drv, dpy, 1) == 1) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); goto fail; } dpy->VersionMajor = 1; dpy->VersionMinor = 4; return EGL_TRUE; fail: if (gdpy) egl_g3d_terminate(drv, dpy); return EGL_FALSE; }
/** * Return true if the given context and surfaces can be made current. */ static EGLBoolean _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint conflict_api; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); /* this is easy */ if (!ctx) { if (draw || read) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); return EGL_TRUE; } /* ctx/draw/read must be all given */ if (draw == NULL || read == NULL) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); /* context stealing from another thread is not allowed */ if (ctx->Binding && ctx->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); /* * The spec says * * "If ctx is current to some other thread, or if either draw or read are * bound to contexts in another thread, an EGL_BAD_ACCESS error is * generated." * * But it also says * * "at most one context may be bound to a particular surface at a given * time" * * The latter is more restrictive so we can check only the latter case. */ if ((draw->CurrentContext && draw->CurrentContext != ctx) || (read->CurrentContext && read->CurrentContext != ctx)) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); /* simply require the configs to be equal */ if (draw->Config != ctx->Config || read->Config != ctx->Config) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); switch (ctx->ClientAPI) { #ifdef EGL_VERSION_1_4 /* OpenGL and OpenGL ES are conflicting */ case EGL_OPENGL_ES_API: conflict_api = EGL_OPENGL_API; break; case EGL_OPENGL_API: conflict_api = EGL_OPENGL_ES_API; break; #endif default: conflict_api = -1; break; } if (conflict_api >= 0 && _eglGetAPIContext(conflict_api)) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); return EGL_TRUE; }
/** * Return true if the given context and surfaces can be made current. */ static EGLBoolean _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) { _EGLThreadInfo *t = _eglGetCurrentThread(); _EGLDisplay *dpy; EGLint conflict_api; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); /* this is easy */ if (!ctx) { if (draw || read) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); return EGL_TRUE; } dpy = ctx->Resource.Display; if (!dpy->Extensions.KHR_surfaceless_context && (draw == NULL || read == NULL)) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); /* * The spec says * * "If ctx is current to some other thread, or if either draw or read are * bound to contexts in another thread, an EGL_BAD_ACCESS error is * generated." * * and * * "at most one context may be bound to a particular surface at a given * time" */ if (ctx->Binding && ctx->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { if (draw->CurrentContext->Binding != t || draw->CurrentContext->ClientAPI != ctx->ClientAPI) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); } if (read && read->CurrentContext && read->CurrentContext != ctx) { if (read->CurrentContext->Binding != t || read->CurrentContext->ClientAPI != ctx->ClientAPI) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); } /* simply require the configs to be equal */ if ((draw && draw->Config != ctx->Config) || (read && read->Config != ctx->Config)) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); switch (ctx->ClientAPI) { /* OpenGL and OpenGL ES are conflicting */ case EGL_OPENGL_ES_API: conflict_api = EGL_OPENGL_API; break; case EGL_OPENGL_API: conflict_api = EGL_OPENGL_ES_API; break; default: conflict_api = -1; break; } if (conflict_api >= 0 && _eglGetAPIContext(conflict_api)) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); return EGL_TRUE; }