BRL-CAD
fb_generic.c
Go to the documentation of this file.
1 /* F B _ G E N E R I C . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1986-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 /** \defgroup fb Framebuffer
22  * \ingroup libfb */
23 /** @{ */
24 /** @file fb_generic.c
25  *
26  * The main table where framebuffers are initialized and prioritized
27  * for run-time access.
28  *
29  */
30 /** @} */
31 
32 #include "common.h"
33 
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40 
41 #include "bsocket.h"
42 #include "bio.h"
43 
44 #include "bu/color.h"
45 #include "bu/log.h"
46 #include "bu/malloc.h"
47 #include "bu/str.h"
48 
49 #include "fb_private.h"
50 #include "fb.h"
51 
52 /**
53  * First element of list is default device when no name given
54  */
55 static
56 fb *_if_list[] = {
57 #ifdef IF_OSGL
58  &osgl_interface,
59 #endif
60 #ifdef IF_WGL
61  &wgl_interface,
62 #endif
63 #ifdef IF_OGL
64  &ogl_interface,
65 #endif
66 #ifdef IF_X
67  &X24_interface,
68 #endif
69 #ifdef IF_TK
70  &tk_interface,
71 #endif
72 #ifdef IF_QT
73  &qt_interface,
74 #endif
76 /* never get any of the following by default */
80  (fb *) 0
81 };
82 
84 {
85  struct fb_internal *new_fb = FB_NULL;
86  BU_GET(new_fb, struct fb_internal);
87  new_fb->if_name = NULL;
88  return new_fb;
89 }
90 
91 void fb_put(fb *ifp)
92 {
93  if (ifp != FB_NULL)
94  BU_PUT(ifp, struct fb_internal);
95 }
96 
97 void fb_set_interface(fb *ifp, const char *interface_type)
98 {
99  int i = 0;
100  if (!ifp) return;
101  while (_if_list[i] != FB_NULL) {
102  if (bu_strncmp(interface_type, _if_list[i]->if_name+5, strlen(interface_type)) == 0) {
103  /* found it, copy its struct in */
104  *ifp = *(_if_list[i]);
105  return;
106  } else {
107  i++;
108  }
109  }
110 }
111 
112 struct fb_platform_specific *
114 {
115  int i = 0;
116  if (!magic) return NULL;
117  while (_if_list[i] != FB_NULL) {
118  if (magic == _if_list[i]->type_magic) {
119  /* found it, get its specific struct */
120  return (*(_if_list[i])).if_existing_get(magic);
121  } else {
122  i++;
123  }
124  }
125  return NULL;
126 }
127 
128 void
130 {
131  int i = 0;
132  if (!fb_p) return;
133  while (_if_list[i] != FB_NULL) {
134  if (fb_p->magic == _if_list[i]->type_magic) {
135  /* found it, clear its specific struct */
136  (*(_if_list[i])).if_existing_put(fb_p);
137  return;
138  } else {
139  i++;
140  }
141  }
142  return;
143 }
144 
145 fb *
146 fb_open_existing(const char *file, int width, int height, struct fb_platform_specific *fb_p)
147 {
148  fb *ifp = (fb *) calloc(sizeof(fb), 1);
149  fb_set_interface(ifp, file);
150  fb_set_magic(ifp, FB_MAGIC);
151  ifp->if_open_existing(ifp, width, height, fb_p);
152  return ifp;
153 }
154 
155 int
156 fb_refresh(fb *ifp, int x, int y, int w, int h)
157 {
158  return ifp->if_refresh(ifp, x, y, w, h);
159 }
160 
161 int
162 fb_configure_window(fb *ifp, int width, int height)
163 {
164  /* unknown/unset framebuffer */
165  if (!ifp || !ifp->if_configure_window || width < 0 || height < 0) {
166  return 0;
167  }
168  return ifp->if_configure_window(ifp, width, height);
169 }
170 
171 void fb_set_name(fb *ifp, const char *name)
172 {
173  if (!ifp) return;
174  /*if (ifp->if_name) bu_free(ifp->if_name, "free pre-existing fb name");*/
175  ifp->if_name = (char *)bu_malloc((unsigned)strlen(name)+1, "if_name");
176  bu_strlcpy(ifp->if_name, name, strlen(name)+1);
177 }
178 
179 char *fb_get_name(fb *ifp)
180 {
181  if (!ifp) return NULL;
182  return ifp->if_name;
183 }
184 
186 {
187  if (!ifp) return 0;
188  return ifp->if_ppixels;
189 }
190 
191 int fb_is_set_fd(fb *ifp, fd_set *infds)
192 {
193  if (!ifp) return 0;
194  if (!infds) return 0;
195  if (!ifp->if_selfd) return 0;
196  if (ifp->if_selfd <= 0) return 0;
197  return FD_ISSET(ifp->if_selfd, infds);
198 }
199 
200 int fb_set_fd(fb *ifp, fd_set *select_list)
201 {
202  if (!ifp) return 0;
203  if (!select_list) return 0;
204  if (!ifp->if_selfd) return 0;
205  if (ifp->if_selfd <= 0) return 0;
206  FD_SET(ifp->if_selfd, select_list);
207  return ifp->if_selfd;
208 }
209 
210 int fb_clear_fd(fb *ifp, fd_set *list)
211 {
212  if (!ifp) return 0;
213  if (!list) return 0;
214  if (!ifp->if_selfd) return 0;
215  if (ifp->if_selfd <= 0) return 0;
216  FD_CLR(ifp->if_selfd, list);
217  return ifp->if_selfd;
218 }
219 
220 void fb_set_magic(fb *ifp, uint32_t magic)
221 {
222  ifp->if_magic = magic;
223 }
224 
225 
226 char *fb_gettype(fb *ifp)
227 {
228  return ifp->if_type;
229 }
230 
231 int fb_getwidth(fb *ifp)
232 {
233  return ifp->if_width;
234 }
235 int fb_getheight(fb *ifp)
236 {
237  return ifp->if_height;
238 }
239 
241 {
242  return ifp->if_max_width;
243 }
245 {
246  return ifp->if_max_height;
247 }
248 
249 
250 int fb_poll(fb *ifp)
251 {
252  return (*ifp->if_poll)(ifp);
253 }
254 
255 long fb_poll_rate(fb *ifp)
256 {
257  return ifp->if_poll_refresh_rate;
258 }
259 
260 int fb_help(fb *ifp)
261 {
262  return (*ifp->if_help)(ifp);
263 }
264 int fb_free(fb *ifp)
265 {
266  return (*ifp->if_free)(ifp);
267 }
268 int fb_clear(fb *ifp, unsigned char *pp)
269 {
270  return (*ifp->if_clear)(ifp, pp);
271 }
272 ssize_t fb_read(fb *ifp, int x, int y, unsigned char *pp, size_t count)
273 {
274  return (*ifp->if_read)(ifp, x, y, pp, count);
275 }
276 ssize_t fb_write(fb *ifp, int x, int y, const unsigned char *pp, size_t count)
277 {
278  return (*ifp->if_write)(ifp, x, y, pp, count);
279 }
280 int fb_rmap(fb *ifp, ColorMap *cmap)
281 {
282  return (*ifp->if_rmap)(ifp, cmap);
283 }
284 int fb_wmap(fb *ifp, const ColorMap *cmap)
285 {
286  return (*ifp->if_wmap)(ifp, cmap);
287 }
288 int fb_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
289 {
290  return (*ifp->if_view)(ifp, xcenter, ycenter, xzoom, yzoom);
291 }
292 int fb_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
293 {
294  return (*ifp->if_getview)(ifp, xcenter, ycenter, xzoom, yzoom);
295 }
296 int fb_setcursor(fb *ifp, const unsigned char *bits, int xb, int yb, int xo, int yo)
297 {
298  return (*ifp->if_setcursor)(ifp, bits, xb, yb, xo, yo);
299 }
300 int fb_cursor(fb *ifp, int mode, int x, int y)
301 {
302  return (*ifp->if_cursor)(ifp, mode, x, y);
303 }
304 int fb_getcursor(fb *ifp, int *mode, int *x, int *y)
305 {
306  return (*ifp->if_getcursor)(ifp, mode, x, y);
307 }
308 int fb_readrect(fb *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
309 {
310  return (*ifp->if_readrect)(ifp, xmin, ymin, width, height, pp);
311 }
312 int fb_writerect(fb *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp)
313 {
314  return (*ifp->if_writerect)(ifp, xmin, ymin, width, height, pp);
315 }
316 int fb_bwreadrect(fb *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
317 {
318  return (*ifp->if_bwreadrect)(ifp, xmin, ymin, width, height, pp);
319 }
320 int fb_bwwriterect(fb *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp)
321 {
322  return (*ifp->if_bwwriterect)(ifp, xmin, ymin, width, height, pp);
323 }
324 
325 
326 #define Malloc_Bomb(_bytes_) \
327  fb_log("\"%s\"(%d) : allocation of %lu bytes failed.\n", \
328  __FILE__, __LINE__, _bytes_)
329 
330 /**
331  * True if the non-null string s is all digits
332  */
333 static int
334 fb_totally_numeric(const char *s)
335 {
336  if (s == (char *)0 || *s == 0)
337  return 0;
338 
339  while (*s) {
340  if (*s < '0' || *s > '9')
341  return 0;
342  s++;
343  }
344 
345  return 1;
346 }
347 
348 
349 /**
350  * Disk interface enable flag. Used so the remote daemon
351  * can turn off the disk interface.
352  */
354 
355 
356 /**
357  * Filler for fb function slots not used by a particular device
358  */
359 int fb_null(fb *ifp)
360 {
361  if (ifp) {
362  FB_CK_FB(ifp);
363  }
364 
365  return 0;
366 }
367 
368 
369 /**
370  * Used by if_*.c routines that don't have programmable cursor patterns.
371  */
372 int fb_null_setcursor(fb *ifp, const unsigned char *UNUSED(bits), int UNUSED(xbits), int UNUSED(ybits), int UNUSED(xorig), int UNUSED(yorig))
373 {
374  if (ifp) {
375  FB_CK_FB(ifp);
376  }
377 
378  return 0;
379 }
380 
381 
382 
383 fb *
384 fb_open(const char *file, int width, int height)
385 {
386  register fb *ifp;
387  int i;
388 
389  if (width < 0 || height < 0)
390  return FB_NULL;
391 
392  ifp = (fb *) calloc(sizeof(fb), 1);
393  if (ifp == FB_NULL) {
394  Malloc_Bomb(sizeof(fb));
395  return FB_NULL;
396  }
397  if (file == NULL || *file == '\0') {
398  /* No name given, check environment variable first. */
399  if ((file = (const char *)getenv("FB_FILE")) == NULL || *file == '\0') {
400  /* None set, use first device as default */
401  *ifp = *(_if_list[0]); /* struct copy */
402  file = ifp->if_name;
403  goto found_interface;
404  }
405  }
406  /*
407  * Determine what type of hardware the device name refers to.
408  *
409  * "file" can in general look like: hostname:/pathname/devname#
410  *
411  * If we have a ':' assume the remote interface
412  * (We don't check to see if it's us. Good for debugging.)
413  * else strip out "/path/devname" and try to look it up in the
414  * device array. If we don't find it assume it's a file.
415  */
416  i = 0;
417  while (_if_list[i] != (fb *)NULL) {
418  if (bu_strncmp(file, _if_list[i]->if_name,
419  strlen(_if_list[i]->if_name)) == 0) {
420  /* found it, copy its struct in */
421  *ifp = *(_if_list[i]);
422  goto found_interface;
423  }
424  i++;
425  }
426 
427  /* Not in list, check special interfaces or disk files */
428  /* "/dev/" protection! */
429  if (bu_strncmp(file, "/dev/", 5) == 0) {
430  fb_log("fb_open: no such device \"%s\".\n", file);
431  free((void *) ifp);
432  return FB_NULL;
433  }
434 
435 #ifdef IF_REMOTE
436  if (fb_totally_numeric(file) || strchr(file, ':') != NULL) {
437  /* We have a remote file name of the form <host>:<file>
438  * or a port number (which assumes localhost) */
439  *ifp = remote_interface;
440  goto found_interface;
441  }
442 #endif /* IF_REMOTE */
443  /* Assume it's a disk file */
444  if (_fb_disk_enable) {
445  *ifp = disk_interface;
446  } else {
447  fb_log("fb_open: no such device \"%s\".\n", file);
448  free((void *) ifp);
449  return FB_NULL;
450  }
451 
452 found_interface:
453  /* Copy over the name it was opened by. */
454  ifp->if_name = (char*)malloc((unsigned) strlen(file) + 1);
455  if (ifp->if_name == (char *)NULL) {
456  Malloc_Bomb(strlen(file) + 1);
457  free((void *) ifp);
458  return FB_NULL;
459  }
460  bu_strlcpy(ifp->if_name, file, strlen(file)+1);
461 
462  /* Mark OK by filling in magic number */
463  ifp->if_magic = FB_MAGIC;
464 
465  if ((i=(*ifp->if_open)(ifp, file, width, height)) <= -1) {
466  fb_log("fb_open: can't open device \"%s\", ret=%d.\n",
467  file, i);
468  ifp->if_magic = 0; /* sanity */
469  free((void *) ifp->if_name);
470  free((void *) ifp);
471  return FB_NULL;
472  }
473  return ifp;
474 }
475 
476 
477 int
479 {
480  int i;
481 
482  FB_CK_FB(ifp);
483  fb_flush(ifp);
484  if ((i=(*ifp->if_close)(ifp)) <= -1) {
485  fb_log("fb_close: can not close device \"%s\", ret=%d.\n",
486  ifp->if_name, i);
487  return -1;
488  }
489  if (ifp->if_pbase != PIXEL_NULL)
490  free((void *) ifp->if_pbase);
491  free((void *) ifp->if_name);
492  free((void *) ifp);
493  return 0;
494 }
495 
496 
497 int
499 {
500  int status = 0;
501  if (!ifp)
502  return 0;
503 
504  FB_CK_FB(ifp);
505 
506  fb_flush(ifp);
507 
508  /* FIXME: these should be callbacks, not listed directly */
509 
510  status = ifp->if_close_existing(ifp);
511 
512  if (status <= -1) {
513  fb_log("fb_close_existing: cannot close device \"%s\", ret=%d.\n", ifp->if_name, status);
514  return BRLCAD_ERROR;
515  }
516  fb_put(ifp);
517  return BRLCAD_OK;
518 }
519 
520 
521 /**
522  * Generic Help.
523  * Print out the list of available frame buffers.
524  */
525 int
527 {
528  int i;
529 
530  i = 0;
531  while (_if_list[i] != (fb *)NULL) {
532  fb_log("%-12s %s\n",
533  _if_list[i]->if_name,
534  _if_list[i]->if_type);
535  i++;
536  }
537 
538  /* Print the ones not in the device list */
539 #ifdef IF_REMOTE
540  fb_log("%-12s %s\n",
543 #endif
544  if (_fb_disk_enable) {
545  fb_log("%-12s %s\n",
548  }
549 
550  return 0;
551 }
552 
553 
554 /**
555  * Check for a color map being linear in the upper 8 bits of R, G, and
556  * B. Returns 1 for linear map, 0 for non-linear map (i.e.,
557  * non-identity map).
558  */
559 int
560 fb_is_linear_cmap(register const ColorMap *cmap)
561 {
562  register int i;
563 
564  for (i=0; i<256; i++) {
565  if (cmap->cm_red[i]>>8 != i) return 0;
566  if (cmap->cm_green[i]>>8 != i) return 0;
567  if (cmap->cm_blue[i]>>8 != i) return 0;
568  }
569  return 1;
570 }
571 
572 
573 void
575 {
576  register int i;
577 
578  for (i=0; i<256; i++) {
579  cmap->cm_red[i] = i<<8;
580  cmap->cm_green[i] = i<<8;
581  cmap->cm_blue[i] = i<<8;
582  }
583 }
584 
585 static void
586 fb_cmap_crunch(RGBpixel (*scan_buf), int pixel_ct, ColorMap *cmap)
587 {
588  unsigned short *rp = cmap->cm_red;
589  unsigned short *gp = cmap->cm_green;
590  unsigned short *bp = cmap->cm_blue;
591 
592  /* noalias ? */
593  for (; pixel_ct > 0; pixel_ct--, scan_buf++ ) {
594  (*scan_buf)[RED] = rp[(*scan_buf)[RED]] >> 8;
595  (*scan_buf)[GRN] = gp[(*scan_buf)[GRN]] >> 8;
596  (*scan_buf)[BLU] = bp[(*scan_buf)[BLU]] >> 8;
597  }
598 }
599 
600 int
601 fb_write_fp(fb *ifp, FILE *fp, int req_width, int req_height, int crunch, int inverse, struct bu_vls *result)
602 {
603  unsigned char *scanline; /* 1 scanline pixel buffer */
604  int scanbytes; /* # of bytes of scanline */
605  int scanpix; /* # of pixels of scanline */
606  ColorMap cmap; /* libfb color map */
607 
608  scanpix = req_width;
609  scanbytes = scanpix * sizeof(RGBpixel);
610  if ((scanline = (unsigned char *)malloc(scanbytes)) == RGBPIXEL_NULL) {
611  bu_vls_printf(result, "fb_write_to_pix_fp: malloc(%d) failure", scanbytes);
612  return BRLCAD_ERROR;
613  }
614 
615  if (req_height > fb_getheight(ifp))
616  req_height = fb_getheight(ifp);
617  if (req_width > fb_getwidth(ifp))
618  req_width = fb_getwidth(ifp);
619 
620  if (crunch) {
621  if (fb_rmap(ifp, &cmap) == -1) {
622  crunch = 0;
623  } else if (fb_is_linear_cmap(&cmap)) {
624  crunch = 0;
625  }
626  }
627 
628  if (!inverse) {
629  int y;
630 
631  /* Regular -- read bottom to top */
632  for (y=0; y < req_height; y++) {
633  fb_read(ifp, 0, y, scanline, req_width);
634  if (crunch)
635  fb_cmap_crunch((RGBpixel *)scanline, scanpix, &cmap);
636  if (fwrite((char *)scanline, scanbytes, 1, fp) != 1) {
637  perror("fwrite");
638  break;
639  }
640  }
641  } else {
642  int y;
643 
644  /* Inverse -- read top to bottom */
645  for (y = req_height-1; y >= 0; y--) {
646  fb_read(ifp, 0, y, scanline, req_width);
647  if (crunch)
648  fb_cmap_crunch((RGBpixel *)scanline, scanpix, &cmap);
649  if (fwrite((char *)scanline, scanbytes, 1, fp) != 1) {
650  perror("fwrite");
651  break;
652  }
653  }
654  }
655 
656  bu_free((void *)scanline, "fb_write_to_pix_fp(): scanline");
657  return BRLCAD_OK;
658 }
659 
660 /*
661  * Throw bytes away. Use reads into scanline buffer if a pipe, else seek.
662  */
663 static int
664 fb_skip_bytes(int fd, off_t num, int fileinput, int scanbytes, unsigned char *scanline)
665 {
666  int n, tries;
667 
668  if (fileinput) {
669  (void)lseek(fd, num, 1);
670  return 0;
671  }
672 
673  while (num > 0) {
674  tries = num > scanbytes ? scanbytes : num;
675  n = read(fd, scanline, tries);
676  if (n <= 0) {
677  return -1;
678  }
679  num -= n;
680  }
681  return 0;
682 }
683 
684 
685 int
686 fb_read_fd(fb *ifp, int fd, int file_width, int file_height, int file_xoff, int file_yoff, int scr_width, int scr_height, int scr_xoff, int scr_yoff, int fileinput, char *file_name, int one_line_only, int multiple_lines, int autosize, int inverse, int clear, int zoom, struct bu_vls *UNUSED(result))
687 {
688  int y;
689  int xout, yout, n, m, xstart, xskip;
690  unsigned char *scanline; /* 1 scanline pixel buffer */
691  int scanbytes; /* # of bytes of scanline */
692  int scanpix; /* # of pixels of scanline */
693 
694  /* autosize input? */
695  if (fileinput && autosize) {
696  size_t w, h;
697  if (fb_common_file_size(&w, &h, file_name, 3)) {
698  file_width = w;
699  file_height = h;
700  } else {
701  fprintf(stderr, "pix-fb: unable to autosize\n");
702  }
703  }
704 
705  /* If screen size was not set, track the file size */
706  if (scr_width == 0)
707  scr_width = file_width;
708  if (scr_height == 0)
709  scr_height = file_height;
710 
711  /* Get the screen size we were given */
712  scr_width = fb_getwidth(ifp);
713  scr_height = fb_getheight(ifp);
714 
715  /* compute number of pixels to be output to screen */
716  if (scr_xoff < 0) {
717  xout = scr_width + scr_xoff;
718  xskip = (-scr_xoff);
719  xstart = 0;
720  } else {
721  xout = scr_width - scr_xoff;
722  xskip = 0;
723  xstart = scr_xoff;
724  }
725 
726  if (xout < 0)
727  bu_exit(0, NULL); /* off screen */
728  if ((size_t)xout > (size_t)(file_width-file_xoff))
729  xout = (file_width-file_xoff);
730  scanpix = xout; /* # pixels on scanline */
731 
732  if (inverse)
733  scr_yoff = (-scr_yoff);
734 
735  yout = scr_height - scr_yoff;
736  if (yout < 0)
737  bu_exit(0, NULL); /* off screen */
738  if ((size_t)yout > (size_t)(file_height-file_yoff))
739  yout = (file_height-file_yoff);
740 
741  /* Only in the simplest case use multi-line writes */
742  if (!one_line_only
743  && multiple_lines > 0
744  && !inverse
745  && !zoom
746  && (size_t)xout == (size_t)file_width
747  && (size_t)file_width <= (size_t)scr_width)
748  {
749  scanpix *= multiple_lines;
750  }
751 
752  scanbytes = scanpix * sizeof(RGBpixel);
753  if ((scanline = (unsigned char *)malloc(scanbytes)) == RGBPIXEL_NULL) {
754  fprintf(stderr,
755  "pix-fb: malloc(%d) failure for scanline buffer\n",
756  scanbytes);
757  bu_exit(2, NULL);
758  }
759 
760  if (clear) {
761  fb_clear(ifp, PIXEL_NULL);
762  }
763  if (zoom) {
764  /* Zoom in, and center the display. Use square zoom. */
765  int zoomit;
766  zoomit = scr_width/xout;
767  if (scr_height/yout < zoomit) zoomit = scr_height/yout;
768  if (inverse) {
769  fb_view(ifp,
770  scr_xoff+xout/2, scr_height-1-(scr_yoff+yout/2),
771  zoomit, zoomit);
772  } else {
773  fb_view(ifp,
774  scr_xoff+xout/2, scr_yoff+yout/2,
775  zoomit, zoomit);
776  }
777  }
778 
779  if (file_yoff != 0) fb_skip_bytes(fd, (off_t)file_yoff*(off_t)file_width*sizeof(RGBpixel), fileinput, scanbytes, scanline);
780 
781  if (multiple_lines) {
782  /* Bottom to top with multi-line reads & writes */
783  unsigned long height;
784  for (y = scr_yoff; y < scr_yoff + yout; y += multiple_lines) {
785  n = bu_mread(fd, (char *)scanline, scanbytes);
786  if (n <= 0) break;
787  height = multiple_lines;
788  if (n != scanbytes) {
789  height = (n/sizeof(RGBpixel)+xout-1)/xout;
790  if (height <= 0) break;
791  }
792  /* Don't over-write */
793  if ((size_t)(y + height) > (size_t)(scr_yoff + yout))
794  height = scr_yoff + yout - y;
795  if (height <= 0) break;
796  m = fb_writerect(ifp, scr_xoff, y,
797  file_width, height,
798  scanline);
799  if ((size_t)m != file_width*height) {
800  fprintf(stderr,
801  "pix-fb: fb_writerect(x=%d, y=%d, w=%lu, h=%lu) failure, ret=%d, s/b=%d\n",
802  scr_xoff, y,
803  (unsigned long)file_width, height, m, scanbytes);
804  }
805  }
806  } else if (!inverse) {
807  /* Normal way -- bottom to top */
808  for (y = scr_yoff; y < scr_yoff + yout; y++) {
809  if (y < 0 || y > scr_height) {
810  fb_skip_bytes(fd, (off_t)file_width*sizeof(RGBpixel), fileinput, scanbytes, scanline);
811  continue;
812  }
813  if (file_xoff+xskip != 0)
814  fb_skip_bytes(fd, (off_t)(file_xoff+xskip)*sizeof(RGBpixel), fileinput, scanbytes, scanline);
815  n = bu_mread(fd, (char *)scanline, scanbytes);
816  if (n <= 0) break;
817  m = fb_write(ifp, xstart, y, scanline, xout);
818  if (m != xout) {
819  fprintf(stderr,
820  "pix-fb: fb_write(x=%d, y=%d, npix=%d) ret=%d, s/b=%d\n",
821  scr_xoff, y, xout,
822  m, xout);
823  }
824  /* slop at the end of the line? */
825  if ((size_t)file_xoff+xskip+scanpix < (size_t)file_width)
826  fb_skip_bytes(fd, (off_t)(file_width-file_xoff-xskip-scanpix)*sizeof(RGBpixel), fileinput, scanbytes, scanline);
827  }
828  } else {
829  /* Inverse -- top to bottom */
830  for (y = scr_height-1-scr_yoff; y >= scr_height-scr_yoff-yout; y--) {
831  if (y < 0 || y >= scr_height) {
832  fb_skip_bytes(fd, (off_t)file_width*sizeof(RGBpixel), fileinput, scanbytes, scanline);
833  continue;
834  }
835  if (file_xoff+xskip != 0)
836  fb_skip_bytes(fd, (off_t)(file_xoff+xskip)*sizeof(RGBpixel), fileinput, scanbytes, scanline);
837  n = bu_mread(fd, (char *)scanline, scanbytes);
838  if (n <= 0) break;
839  m = fb_write(ifp, xstart, y, scanline, xout);
840  if (m != xout) {
841  fprintf(stderr,
842  "pix-fb: fb_write(x=%d, y=%d, npix=%d) ret=%d, s/b=%d\n",
843  scr_xoff, y, xout,
844  m, xout);
845  }
846  /* slop at the end of the line? */
847  if ((size_t)file_xoff+xskip+scanpix < (size_t)file_width)
848  fb_skip_bytes(fd, (off_t)(file_width-file_xoff-xskip-scanpix)*sizeof(RGBpixel), fileinput, scanbytes, scanline);
849  }
850  }
851  free(scanline);
852  return BRLCAD_OK;
853 }
854 
855 
856 /*
857  * Local Variables:
858  * mode: C
859  * tab-width: 8
860  * indent-tabs-mode: t
861  * c-file-style: "stroustrup"
862  * End:
863  * ex: shiftwidth=4 tabstop=8
864  */
int fb_is_linear_cmap(register const ColorMap *cmap)
Definition: fb_generic.c:560
char * fb_gettype(fb *ifp)
Definition: fb_generic.c:226
long if_poll_refresh_rate
Recommended polling rate for interactive framebuffers in microseconds.
Definition: fb_private.h:135
ptrdiff_t ssize_t
Definition: common.h:119
int fb_refresh(fb *ifp, int x, int y, int w, int h)
Definition: fb_generic.c:156
unsigned char RGBpixel[3]
Definition: fb.h:73
int fb_write_fp(fb *ifp, FILE *fp, int req_width, int req_height, int crunch, int inverse, struct bu_vls *result)
Definition: fb_generic.c:601
int(* if_readrect)(struct fb_internal *ifp, int xmin, int ymin, int _width, int _height, unsigned char *pp)
read rectangle
Definition: fb_private.h:100
int(* if_close_existing)(struct fb_internal *ifp)
close embedded fb
Definition: fb_private.h:86
int(* if_open_existing)(struct fb_internal *ifp, int width, int height, struct fb_platform_specific *fb_p)
open device
Definition: fb_private.h:85
int fb_genhelp(void)
Definition: fb_generic.c:526
void fb_log(const char *fmt,...) _BU_ATTR_PRINTF12
Definition: fb_log.c:42
ssize_t scanbytes
Definition: rot.c:53
unsigned short cm_green[256]
Definition: fb.h:84
int fb_help(fb *ifp)
Definition: fb_generic.c:260
int(* if_view)(struct fb_internal *ifp, int xcent, int ycent, int xzoom, int yzoom)
set view
Definition: fb_private.h:95
if lu s
Definition: nmg_mod.c:3860
Definition: clone.c:90
int(* if_bwwriterect)(struct fb_internal *ifp, int xmin, int ymin, int _width, int _height, const unsigned char *pp)
write rectangle
Definition: fb_private.h:103
int fb_null(fb *ifp)
Definition: fb_generic.c:359
#define Malloc_Bomb(_bytes_)
Definition: fb_generic.c:326
#define RED
Definition: color.h:39
int fb_close_existing(fb *ifp)
Definition: fb_generic.c:498
int(* if_open)(struct fb_internal *ifp, const char *file, int _width, int _height)
open device
Definition: fb_private.h:84
int(* if_help)(struct fb_internal *ifp)
print useful info
Definition: fb_private.h:109
fb * fb_open(const char *file, int width, int height)
Definition: fb_generic.c:384
#define PIXEL_NULL
Definition: fb.h:89
uint32_t if_magic
Definition: fb_private.h:81
int(* if_setcursor)(struct fb_internal *ifp, const unsigned char *bits, int xb, int yb, int xo, int yo)
define cursor
Definition: fb_private.h:97
Header file for the BRL-CAD common definitions.
int(* if_getview)(struct fb_internal *ifp, int *xcent, int *ycent, int *xzoom, int *yzoom)
get view
Definition: fb_private.h:96
int fb_getcursor(fb *ifp, int *mode, int *x, int *y)
Definition: fb_generic.c:304
int if_max_width
max device width
Definition: fb_private.h:111
int fb_read_fd(fb *ifp, int fd, int file_width, int file_height, int file_xoff, int file_yoff, int scr_width, int scr_height, int scr_xoff, int scr_yoff, int fileinput, char *file_name, int one_line_only, int multiple_lines, int autosize, int inverse, int clear, int zoom, struct bu_vls *result)
Definition: fb_generic.c:686
void fb_put(fb *ifp)
Definition: fb_generic.c:91
#define BLU
Definition: color.h:41
int fb_getheight(fb *ifp)
Definition: fb_generic.c:235
ustring width
int fb_cursor(fb *ifp, int mode, int x, int y)
Definition: fb_generic.c:300
int _fb_disk_enable
Definition: fb_generic.c:353
char * if_type
what "open" calls it
Definition: fb_private.h:110
struct fb_platform_specific * fb_get_platform_specific(uint32_t magic)
Definition: fb_generic.c:113
int fb_bwwriterect(fb *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp)
Definition: fb_generic.c:320
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
long if_ppixels
Sizeof page buffer (pixels).
Definition: fb_private.h:133
int(* if_getcursor)(struct fb_internal *ifp, int *mode, int *x, int *y)
get cursor
Definition: fb_private.h:99
char * strchr(const char *sp, int c)
void fb_set_magic(fb *ifp, uint32_t magic)
Definition: fb_generic.c:220
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
ssize_t(* if_read)(struct fb_internal *ifp, int x, int y, unsigned char *pp, size_t count)
read pixels
Definition: fb_private.h:91
int fb_close(fb *ifp)
Definition: fb_generic.c:478
int fb_free(fb *ifp)
Definition: fb_generic.c:264
int if_selfd
select(fd) for input events if >= 0
Definition: fb_private.h:117
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
int(* if_rmap)(struct fb_internal *ifp, ColorMap *cmap)
read colormap
Definition: fb_private.h:93
#define FB_CK_FB(_p)
Definition: fb.h:100
long fb_get_pagebuffer_pixel_size(fb *ifp)
Definition: fb_generic.c:185
#define FB_NULL
Definition: fb.h:95
fb stk_interface
Definition: if_stack.c:435
fb memory_interface
Definition: if_mem.c:471
int fb_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
Definition: fb_generic.c:288
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
#define BRLCAD_OK
Definition: defines.h:71
unsigned char * bp
Definition: rot.c:56
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
int(* if_configure_window)(struct fb_internal *ifp, int width, int height)
configure window
Definition: fb_private.h:104
ssize_t xout
Definition: rot.c:61
unsigned short cm_red[256]
Definition: fb.h:83
fb null_interface
Definition: if_null.c:257
int fb_getwidth(fb *ifp)
Definition: fb_generic.c:231
int if_max_height
max device height
Definition: fb_private.h:112
int fb_null_setcursor(fb *ifp, const unsigned char *bits, int xbits, int ybits, int xorig, int yorig)
Definition: fb_generic.c:372
oldeumate l2 magic
Definition: nmg_mod.c:3843
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
int(* if_bwreadrect)(struct fb_internal *ifp, int xmin, int ymin, int _width, int _height, unsigned char *pp)
read monochrome rectangle
Definition: fb_private.h:102
int fb_clear_fd(fb *ifp, fd_set *list)
Definition: fb_generic.c:210
#define FB_MAGIC
Definition: magic.h:180
long int bu_mread(int fd, void *bufp, long int n)
Definition: mread.c:31
#define RGBPIXEL_NULL
Definition: fb.h:90
int fb_configure_window(fb *ifp, int width, int height)
Definition: fb_generic.c:162
int fb_readrect(fb *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
Definition: fb_generic.c:308
int(* if_free)(struct fb_internal *ifp)
free resources
Definition: fb_private.h:108
int fb_is_set_fd(fb *ifp, fd_set *infds)
Definition: fb_generic.c:191
int(* if_close)(struct fb_internal *ifp)
close device
Definition: fb_private.h:89
Definition: fb.h:82
ssize_t yout
Definition: rot.c:61
int fb_rmap(fb *ifp, ColorMap *cmap)
Definition: fb_generic.c:280
fb * fb_open_existing(const char *file, int width, int height, struct fb_platform_specific *fb_p)
Definition: fb_generic.c:146
int(* if_cursor)(struct fb_internal *ifp, int mode, int x, int y)
set cursor
Definition: fb_private.h:98
int fb_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
Definition: fb_generic.c:292
HIDDEN int zoom(struct ged *gedp, double sf)
Definition: zoom.c:26
fb * fb_get()
Definition: fb_generic.c:83
ssize_t fb_write(fb *ifp, int x, int y, const unsigned char *pp, size_t count)
Definition: fb_generic.c:276
int fb_common_file_size(size_t *widthp, size_t *heightp, const char *filename, int pixel_size)
Definition: asize.c:86
int fb_wmap(fb *ifp, const ColorMap *cmap)
Definition: fb_generic.c:284
uint32_t magic
Definition: fb.h:176
long fb_poll_rate(fb *ifp)
Definition: fb_generic.c:255
uint32_t type_magic
Definition: fb_private.h:82
int fb_flush(fb *ifp)
int fb_set_fd(fb *ifp, fd_set *select_list)
Definition: fb_generic.c:200
int(* if_refresh)(struct fb_internal *ifp, int x, int y, int w, int h)
refresh window
Definition: fb_private.h:105
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
void fb_set_name(fb *ifp, const char *name)
Definition: fb_generic.c:171
int(* if_wmap)(struct fb_internal *ifp, const ColorMap *cmap)
write colormap
Definition: fb_private.h:94
int fb_clear(fb *ifp, unsigned char *pp)
Definition: fb_generic.c:268
int(* if_writerect)(struct fb_internal *ifp, int xmin, int ymin, int _width, int _height, const unsigned char *pp)
write rectangle
Definition: fb_private.h:101
fb remote_interface
Definition: if_remote.c:788
int fb_bwreadrect(fb *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
Definition: fb_generic.c:316
int(* if_poll)(struct fb_internal *ifp)
handle events
Definition: fb_private.h:106
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
ssize_t(* if_write)(struct fb_internal *ifp, int x, int y, const unsigned char *pp, size_t count)
write pixels
Definition: fb_private.h:92
char * file_name
Definition: fb2pix.c:40
A frame-buffer IO structure.
Definition: fb_private.h:80
fb qt_interface
Definition: if_qt.cpp:1347
int if_width
current values
Definition: fb_private.h:115
fb disk_interface
Definition: if_disk.c:356
int fb_get_max_height(fb *ifp)
Definition: fb_generic.c:244
int fb_get_max_width(fb *ifp)
Definition: fb_generic.c:240
unsigned short cm_blue[256]
Definition: fb.h:85
void fb_set_interface(fb *ifp, const char *interface_type)
Definition: fb_generic.c:97
#define GRN
Definition: color.h:40
int(* if_clear)(struct fb_internal *ifp, unsigned char *pp)
clear device
Definition: fb_private.h:90
Definition: vls.h:56
#define BRLCAD_ERROR
Definition: defines.h:72
char * fb_get_name(fb *ifp)
Definition: fb_generic.c:179
char * if_name
what the user called it
Definition: fb_private.h:114
void fb_make_linear_cmap(register ColorMap *cmap)
Definition: fb_generic.c:574
fb debug_interface
Definition: if_debug.c:362
int fb_setcursor(fb *ifp, const unsigned char *bits, int xb, int yb, int xo, int yo)
Definition: fb_generic.c:296
int fb_writerect(fb *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp)
Definition: fb_generic.c:312
ssize_t fb_read(fb *ifp, int x, int y, unsigned char *pp, size_t count)
Definition: fb_generic.c:272
void fb_put_platform_specific(struct fb_platform_specific *fb_p)
Definition: fb_generic.c:129
int fb_poll(fb *ifp)
Definition: fb_generic.c:250
unsigned char * if_pbase
Address of malloc()ed page buffer.
Definition: fb_private.h:127