int PDC_scr_open()

in graphics/pdcurs34/nuttx/pdcscrn.c [419:687]


int PDC_scr_open(int argc, char **argv)
{
#ifdef CONFIG_PDCURSES_MULTITHREAD
  FAR struct pdc_context_s *ctx = PDC_ctx();
#endif
#ifdef CONFIG_SYSTEM_TERMCURSES
  FAR char *env_display;
#endif
  FAR struct pdc_fbscreen_s *fbscreen;
  FAR const struct nx_font_s *fontset;
  FAR struct pdc_fbstate_s *fbstate;
  struct fb_videoinfo_s vinfo;
  struct fb_planeinfo_s pinfo;
  int ret;
  int i;

  PDC_LOG(("PDC_scr_open() - called\n"));

#ifdef CONFIG_SYSTEM_TERMCURSES
  /* When termcurses is compiled in, we must allow opening terminal
   * type screens also.  Check if the DISPLAY environment variable is
   * set to ":0" indicating we should open the graphic screen.
   */

  env_display = getenv("DISPLAY");
  if (!env_display || strcmp(env_display, ":0") != 0)
    {
      /* Perform terminal open operation */

      return PDC_scr_open_term(argc, argv);
    }
#endif

  /* Allocate the global instance of SP */

  fbscreen =
    (FAR struct pdc_fbscreen_s *)zalloc(sizeof(struct pdc_fbscreen_s));
  if (fbscreen == NULL)
    {
      PDC_LOG(("ERROR: Failed to allocate SP\n"));
      return ERR;
    }

  SP      = &fbscreen->screen;
  fbstate = &fbscreen->fbstate;
#ifdef CONFIG_SYSTEM_TERMCURSES
  graphic_screen = true;
#endif

  /* Number of RGB colors/greyscale levels.  This is the same as the
   * dimension of rgbcolor[] or greylevel[]).
   */

  COLORS = 16;

  /* Setup initial RGB colors */

  for (i = 0; i < 8; i++)
    {
#ifdef PDCURSES_MONOCHROME
      uint8_t greylevel;

      greylevel                      = (i & COLOR_RED)   ? 0x40 : 0;
      greylevel                     += (i & COLOR_GREEN) ? 0x40 : 0;
      greylevel                     += (i & COLOR_BLUE)  ? 0x40 : 0;

      fbstate->greylevel[i]          = greylevel;
      fbstate->greylevel[i + 8]      = greylevel | 0x3f;
#else
      fbstate->rgbcolor[i].red       = (i & COLOR_RED)   ? 0xc0 : 0;
      fbstate->rgbcolor[i].green     = (i & COLOR_GREEN) ? 0xc0 : 0;
      fbstate->rgbcolor[i].blue      = (i & COLOR_BLUE)  ? 0xc0 : 0;

      fbstate->rgbcolor[i + 8].red   = (i & COLOR_RED)   ? 0xff : 0x40;
      fbstate->rgbcolor[i + 8].green = (i & COLOR_GREEN) ? 0xff : 0x40;
      fbstate->rgbcolor[i + 8].blue  = (i & COLOR_BLUE)  ? 0xff : 0x40;
#endif
    }

  /* Open the framebuffer driver */

  fbstate->fbfd = open(CONFIG_PDCURSES_FBDEV, O_RDWR);
  if (fbstate->fbfd < 0)
    {
      PDC_LOG(("ERROR: Failed to open %s: %d\n",
               CONFIG_PDCURSES_FBDEV, errno));
      goto errout_with_sp;
    }

  /* Get the characteristics of the framebuffer */

  ret = ioctl(fbstate->fbfd, FBIOGET_VIDEOINFO,
              (unsigned long)((uintptr_t)&vinfo));
  if (ret < 0)
    {
      PDC_LOG(("ERROR: ioctl(FBIOGET_VIDEOINFO) failed: %d\n", errno));
      goto errout_with_fbfd;
    }

  PDC_LOG(("VideoInfo:\n"));
  PDC_LOG(("      fmt: %u\n", vinfo.fmt));
  PDC_LOG(("     xres: %u\n", vinfo.xres));
  PDC_LOG(("     yres: %u\n", vinfo.yres));
  PDC_LOG(("  nplanes: %u\n", vinfo.nplanes));

  fbstate->xres = vinfo.xres;  /* Horizontal resolution in pixel columns */
  fbstate->yres = vinfo.yres;  /* Vertical resolution in pixel rows */

  /* Only one color format supported. */

  if (vinfo.fmt != PDCURSES_COLORFMT)
    {
      PDC_LOG(("ERROR: color format=%u not supported\n", vinfo.fmt));
      goto errout_with_fbfd;
    }

#ifdef PDCURSES_MONOCHROME
  /* Remember if we are using a monochrome framebuffer */

  SP->mono = true;
#endif

  /* Get characteristics of the color plane */

  ret = ioctl(fbstate->fbfd, FBIOGET_PLANEINFO,
              (unsigned long)((uintptr_t)&pinfo));
  if (ret < 0)
    {
      PDC_LOG(("ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n", errno));
      goto errout_with_fbfd;
    }

  PDC_LOG(("PlaneInfo (plane 0):\n"));
  PDC_LOG(("    fbmem: %p\n", pinfo.fbmem));
  PDC_LOG(("    fblen: %lu\n", (unsigned long)pinfo.fblen));
  PDC_LOG(("   stride: %u\n", pinfo.stride));
  PDC_LOG(("  display: %u\n", pinfo.display));
  PDC_LOG(("      bpp: %u\n", pinfo.bpp));

  fbstate->stride = pinfo.stride; /* Length of a line in bytes */

  /* Only one pixel depth is supported. */

  if (pinfo.bpp != PDCURSES_BPP)
    {
      PDC_LOG(("ERROR: bpp=%u not supported\n", pinfo.bpp));
      goto errout_with_fbfd;
    }

  /* mmap() the framebuffer.
   *
   * NOTE: In the FLAT build the frame buffer address returned by the
   * FBIOGET_PLANEINFO IOCTL command will be the same as the framebuffer
   * address.  mmap(), however, is the preferred way to get the framebuffer
   * address because in the KERNEL build, it will perform the necessary
   * address mapping to make the memory accessible to the application.
   */

  fbstate->fbmem = mmap(NULL, pinfo.fblen, PROT_READ | PROT_WRITE,
                        MAP_SHARED | MAP_FILE, fbstate->fbfd, 0);
  if (fbstate->fbmem == MAP_FAILED)
    {
      PDC_LOG(("ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n", errno));
      goto errout_with_fbfd;
    }

  PDC_LOG(("Mapped FB: %p\n", fbstate->fbmem));

  /* Get the handle for the selected font */

  fbstate->hfont = nxf_getfonthandle(PDCURSES_FONTID);
  if (fbstate->hfont == NULL)
    {
      PDC_LOG(("ERROR: Failed to get font handle: %d\n", errno));
      goto errout_with_fbfd;
    }

#ifdef HAVE_BOLD_FONT
  /* Get the handle for the matching bold font.  It is assume that the
   * geometry of the bold font is exactly the same as the geometry of
   * the "normal" font.
   */

  fbstate->hbold = nxf_getfonthandle(PDCURSES_BOLD_FONTID);
  if (fbstate->hbold == NULL)
    {
      PDC_LOG(("ERROR: Failed to get font handle: %d\n", errno));
      goto errout_with_font;
    }
#endif

  /* Get information about the fontset */

  fontset = nxf_getfontset(fbstate->hfont);
  if (fontset == NULL)
    {
      PDC_LOG(("ERROR: Failed to get font handle: %d\n", errno));
      goto errout_with_boldfont;
    }

  PDC_LOG(("Fontset (ID=%d):\n", PDCURSES_FONTID));
  PDC_LOG((" mxheight: %u\n", fontset->mxheight));
  PDC_LOG(("  mxwidth: %u\n", fontset->mxwidth));
  PDC_LOG(("   mxbits: %u\n", fontset->mxbits));
  PDC_LOG(("  spwidth: %u\n", fontset->spwidth));

  fbstate->fheight = fontset->mxheight;
  fbstate->fwidth  = fontset->mxwidth;

#if PDCURSES_BPP < 8
  /* Allocate the font buffer for < 8-bit display */

  fbstate->fstride =
    (fbstate->fwidth + PDCURSES_PPB_MASK) >> PDCURSES_PPB_SHIFT;
  fbstate->fbuffer  = (FAR uint8_t *)
    malloc(fbstate->fstride * fbstate->fheight);

  if (fbstate->fbuffer == NULL)
    {
      PDC_LOG(("ERROR: Failed to allocate fstride: %d\n", errno));
      goto errout_with_boldfont;
    }
#endif

  /* Calculate the drawable region */

  SP->lines        = fbstate->yres / fbstate->fheight;
  SP->cols         = fbstate->xres / fbstate->fwidth;

  fbstate->hoffset = (fbstate->xres - fbstate->fwidth * SP->cols) / 2;
  fbstate->voffset = (fbstate->yres - fbstate->fheight * SP->lines) / 2;

  /* Set the framebuffer to a known state */

  PDC_clear_screen(fbstate);

#ifdef CONFIG_PDCURSES_HAVE_INPUT
  /* Open and configure any input devices */

  ret = PDC_input_open(fbstate);
  if (ret == ERR)
    {
      goto errout_with_fbuffer;
    }
#endif

  return OK;

#ifdef CONFIG_PDCURSES_HAVE_INPUT
errout_with_fbuffer:
#if PDCURSES_BPP < 8
  free(fbstate->fbuffer);
#endif
#endif

errout_with_boldfont:
#ifdef HAVE_BOLD_FONT
errout_with_font:
#endif

errout_with_fbfd:
  close(fbstate->fbfd);
  fbstate->fbfd = -1;

errout_with_sp:
  free(SP);
  SP = NULL;
  return ERR;
}