Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
/**
 * 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;
}
Beispiel #4
0
/**
 * 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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
/**
 * 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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
/**
 * 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;
}
Beispiel #12
0
/**
 * 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;
}
Beispiel #13
0
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;
}
Beispiel #14
0
/**
 * 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;
}
Beispiel #15
0
/**
 * 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;
}