BRL-CAD
if_mem.c
Go to the documentation of this file.
1 /* I F _ M E M . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1989-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 /** @addtogroup if */
21 /** @{ */
22 /** @file if_mem.c
23  *
24  * A Memory (virtual) Frame Buffer Interface.
25  *
26  */
27 /** @} */
28 
29 #include "common.h"
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <string.h>
35 
36 #include "bu/color.h"
37 #include "bu/log.h"
38 #include "bu/str.h"
39 #include "fb_private.h"
40 #include "fb.h"
41 
42 
43 /* Per connection private info */
44 struct mem_info {
45  fb *fbp; /* attached frame buffer (if any) */
46  unsigned char *mem; /* memory frame buffer */
47  ColorMap cmap; /* color map buffer */
48  int mem_dirty; /* !0 implies unflushed written data */
49  int cmap_dirty; /* !0 implies unflushed written cmap */
50  int write_thru; /* !0 implies pass-thru write mode */
51 };
52 #define MI(ptr) ((struct mem_info *)((ptr)->u1.p))
53 #define MIL(ptr) ((ptr)->u1.p) /* left hand side version */
54 
55 #define MODE_1MASK (1<<1)
56 #define MODE_1BUFFERED (0<<1) /* output flushed only at close */
57 #define MODE_1IMMEDIATE (1<<1) /* pass-through writes */
58 
59 #define MODE_2MASK (1<<2)
60 #define MODE_2CLEAR (0<<2) /* assume fb opens clear */
61 #define MODE_2PREREAD (1<<2) /* pre-read data from fb */
62 
63 static struct modeflags {
64  char c;
65  long mask;
66  long value;
67  char *help;
68 } modeflags[] = {
70  "Write thru mode - pass writes directly to attached frame buffer" },
71  { 'r', MODE_2MASK, MODE_2PREREAD,
72  "Pre-Read attached frame buffer data - else assumes clear" },
73  { '\0', 0, 0, "" }
74 };
75 
76 
77 HIDDEN int
78 mem_open(fb *ifp, const char *file, int width, int height)
79 {
80  int mode;
81  const char *cp;
82  fb *fbp;
83  char modebuf[80];
84  char *mp;
85  int alpha;
86  struct modeflags *mfp;
87 
88  FB_CK_FB(ifp);
89 
90  /* This function doesn't look like it will work if file
91  * is NULL - stop before we start, if that's the case.*/
92  if (file == NULL) return -1;
93 
94  /*
95  * First, attempt to determine operating mode for this open,
96  * based upon the "unit number" or flags.
97  * file = "/dev/mem###"
98  * The default mode is zero.
99  */
100  mode = 0;
101 
102  if (bu_strncmp(file, "/dev/mem", 8)) {
103  /* How did this happen?? */
104  mode = 0;
105  } else {
106  /* Parse the options */
107  alpha = 0;
108  mp = &modebuf[0];
109  cp = &file[8];
110  while (*cp != '\0' && !isspace((int)*cp)) {
111  *mp++ = *cp; /* copy it to buffer */
112  if (isdigit((int)*cp)) {
113  cp++;
114  continue;
115  }
116  alpha++;
117  for (mfp = modeflags; mfp->c != '\0'; mfp++) {
118  if (mfp->c == *cp) {
119  mode = (mode&~mfp->mask)|mfp->value;
120  break;
121  }
122  }
123  if (mfp->c == '\0' && *cp != '-') {
124  fb_log("if_mem: unknown option '%c' ignored\n", *cp);
125  }
126  cp++;
127  }
128  *mp = '\0';
129  if (!alpha)
130  mode = atoi(modebuf);
131  }
132 
133  /* build a local static info struct */
134  if ((MIL(ifp) = (char *)calloc(1, sizeof(struct mem_info))) == NULL) {
135  fb_log("mem_open: mem_info malloc failed\n");
136  return -1;
137  }
138  cp = &file[strlen("/dev/mem")];
139  while (*cp != '\0' && *cp != ' ' && *cp != '\t')
140  cp++; /* skip suffix */
141  while (*cp != '\0' && (*cp == ' ' || *cp == '\t' || *cp == ';'))
142  cp++; /* skip blanks and separators */
143 
144  if (*cp) {
145  /* frame buffer device specified */
146  if ((fbp = fb_open(cp, width, height)) == FB_NULL) {
147  free(MIL(ifp));
148  return -1;
149  }
150  MI(ifp)->fbp = fbp;
151  ifp->if_width = fbp->if_width;
152  ifp->if_height = fbp->if_height;
153  ifp->if_selfd = fbp->if_selfd;
154  if ((mode & MODE_1MASK) == MODE_1IMMEDIATE)
155  MI(ifp)->write_thru = 1;
156  } else {
157  /* no frame buffer specified */
158  if (width > 0)
159  ifp->if_width = width;
160  if (height > 0)
161  ifp->if_height = height;
162  }
163  if ((MI(ifp)->mem = (unsigned char *)calloc(ifp->if_width*ifp->if_height, 3)) == NULL) {
164  fb_log("mem_open: memory buffer malloc failed\n");
165  (void)free(MIL(ifp));
166  return -1;
167  }
168  if ((MI(ifp)->fbp != FB_NULL)
169  && (mode & MODE_2MASK) == MODE_2PREREAD) {
170  /* Pre read all of the image data and cmap */
171  int got;
172  got = fb_readrect(MI(ifp)->fbp, 0, 0,
173  ifp->if_width, ifp->if_height,
174  (unsigned char *)MI(ifp)->mem);
175  if (got != ifp->if_width * ifp->if_height) {
176  fb_log("if_mem: WARNING: pre-read of %d only got %d, your image is truncated.\n",
177  ifp->if_width * ifp->if_height, got);
178  }
179  if (fb_rmap(MI(ifp)->fbp, &(MI(ifp)->cmap)) < 0)
180  fb_make_linear_cmap(&(MI(ifp)->cmap));
181  } else {
182  /* Image data begins black, colormap linear */
183  fb_make_linear_cmap(&(MI(ifp)->cmap));
184  }
185 
186  return 0;
187 }
188 
191 {
192  return NULL;
193 }
194 
195 
196 HIDDEN void
198 {
199  return;
200 }
201 
202 HIDDEN int
203 mem_open_existing(fb *UNUSED(ifp), int UNUSED(width), int UNUSED(height), struct fb_platform_specific *UNUSED(fb_p))
204 {
205  return 0;
206 }
207 
208 HIDDEN int
210 {
211  return 0;
212 }
213 
214 HIDDEN int
215 mem_configure_window(fb *UNUSED(ifp), int UNUSED(width), int UNUSED(height))
216 {
217  return 0;
218 }
219 
220 HIDDEN int
221 mem_refresh(fb *UNUSED(ifp), int UNUSED(x), int UNUSED(y), int UNUSED(w), int UNUSED(h))
222 {
223  return 0;
224 }
225 
226 HIDDEN int
228 {
229  /*
230  * Flush memory/cmap to attached frame buffer if any
231  */
232  if (MI(ifp)->fbp != FB_NULL) {
233  if (MI(ifp)->cmap_dirty) {
234  fb_wmap(MI(ifp)->fbp, &(MI(ifp)->cmap));
235  }
236  if (MI(ifp)->mem_dirty) {
237  fb_writerect(MI(ifp)->fbp, 0, 0,
238  ifp->if_width, ifp->if_height, (unsigned char *)MI(ifp)->mem);
239  }
240  fb_close(MI(ifp)->fbp);
241  MI(ifp)->fbp = FB_NULL;
242  }
243  (void)free((char *)MI(ifp)->mem);
244  (void)free((char *)MIL(ifp));
245 
246  return 0;
247 }
248 
249 
250 HIDDEN int
251 mem_clear(fb *ifp, unsigned char *pp)
252 {
253  RGBpixel v;
254  register int n;
255  register unsigned char *cp;
256 
257  if (pp == RGBPIXEL_NULL) {
258  v[RED] = v[GRN] = v[BLU] = 0;
259  } else {
260  v[RED] = (pp)[RED];
261  v[GRN] = (pp)[GRN];
262  v[BLU] = (pp)[BLU];
263  }
264 
265  cp = MI(ifp)->mem;
266  if (v[RED] == v[GRN] && v[RED] == v[BLU]) {
267  int bytes = ifp->if_width*ifp->if_height*3;
268  if (v[RED] == 0)
269  memset((char *)cp, 0, bytes); /* all black */
270  else
271  memset(cp, v[RED], bytes); /* all grey */
272  } else {
273  for (n = ifp->if_width*ifp->if_height; n; n--) {
274  *cp++ = v[RED];
275  *cp++ = v[GRN];
276  *cp++ = v[BLU];
277  }
278  }
279  if (MI(ifp)->write_thru) {
280  return fb_clear(MI(ifp)->fbp, pp);
281  } else {
282  MI(ifp)->mem_dirty = 1;
283  }
284  return 0;
285 }
286 
287 
289 mem_read(fb *ifp, int x, int y, unsigned char *pixelp, size_t count)
290 {
291  size_t pixels_to_end;
292 
293  if (x < 0 || x >= ifp->if_width || y < 0 || y >= ifp->if_height)
294  return -1;
295 
296  /* make sure we don't run off the end of the buffer */
297  pixels_to_end = ifp->if_width*ifp->if_height - (y*ifp->if_width + x);
298  if (pixels_to_end < count)
299  count = pixels_to_end;
300 
301  memcpy((char *)pixelp, &(MI(ifp)->mem[(y*ifp->if_width + x)*3]), count*3);
302 
303  return count;
304 }
305 
306 
308 mem_write(fb *ifp, int x, int y, const unsigned char *pixelp, size_t count)
309 {
310  size_t pixels_to_end;
311 
312  if (x < 0 || x >= ifp->if_width || y < 0 || y >= ifp->if_height)
313  return -1;
314 
315  /* make sure we don't run off the end of the buffer */
316  pixels_to_end = ifp->if_width*ifp->if_height - (y*ifp->if_width + x);
317  if (pixels_to_end < count)
318  count = pixels_to_end;
319 
320  memcpy(&(MI(ifp)->mem[(y*ifp->if_width + x)*3]), (char *)pixelp, count*3);
321 
322  if (MI(ifp)->write_thru) {
323  return fb_write(MI(ifp)->fbp, x, y, pixelp, count);
324  } else {
325  MI(ifp)->mem_dirty = 1;
326  }
327  return count;
328 }
329 
330 
331 HIDDEN int
332 mem_rmap(fb *ifp, ColorMap *cmp)
333 {
334  *cmp = MI(ifp)->cmap; /* struct copy */
335  return 0;
336 }
337 
338 
339 HIDDEN int
340 mem_wmap(fb *ifp, const ColorMap *cmp)
341 {
342  if (cmp == COLORMAP_NULL) {
343  fb_make_linear_cmap(&(MI(ifp)->cmap));
344  } else {
345  MI(ifp)->cmap = *cmp; /* struct copy */
346  }
347 
348  if (MI(ifp)->write_thru) {
349  return fb_wmap(MI(ifp)->fbp, cmp);
350  } else {
351  MI(ifp)->cmap_dirty = 1;
352  }
353  return 0;
354 }
355 
356 
357 HIDDEN int
358 mem_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
359 {
360  fb_sim_view(ifp, xcenter, ycenter, xzoom, yzoom);
361  if (MI(ifp)->write_thru) {
362  return fb_view(MI(ifp)->fbp, xcenter, ycenter,
363  xzoom, yzoom);
364  }
365  return 0;
366 }
367 
368 
369 HIDDEN int
370 mem_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
371 {
372  if (MI(ifp)->write_thru) {
373  return fb_getview(MI(ifp)->fbp, xcenter, ycenter,
374  xzoom, yzoom);
375  }
376  fb_sim_getview(ifp, xcenter, ycenter, xzoom, yzoom);
377  return 0;
378 }
379 
380 
381 HIDDEN int
382 mem_setcursor(fb *ifp, const unsigned char *bits, int xbits, int ybits, int xorig, int yorig)
383 {
384  if (MI(ifp)->write_thru) {
385  return fb_setcursor(MI(ifp)->fbp,
386  bits, xbits, ybits, xorig, yorig);
387  }
388  return 0;
389 }
390 
391 
392 HIDDEN int
393 mem_cursor(fb *ifp, int mode, int x, int y)
394 {
395  fb_sim_cursor(ifp, mode, x, y);
396  if (MI(ifp)->write_thru) {
397  return fb_cursor(MI(ifp)->fbp, mode, x, y);
398  }
399  return 0;
400 }
401 
402 
403 HIDDEN int
404 mem_getcursor(fb *ifp, int *mode, int *x, int *y)
405 {
406  if (MI(ifp)->write_thru) {
407  return fb_getcursor(MI(ifp)->fbp, mode, x, y);
408  }
409  fb_sim_getcursor(ifp, mode, x, y);
410  return 0;
411 }
412 
413 
414 HIDDEN int
416 {
417  if (MI(ifp)->write_thru) {
418  return fb_poll(MI(ifp)->fbp);
419  }
420  return 0;
421 }
422 
423 
424 HIDDEN int
426 {
427  /*
428  * Flush memory/cmap to attached frame buffer if any
429  */
430  if (MI(ifp)->fbp != FB_NULL) {
431  if (MI(ifp)->cmap_dirty) {
432  fb_wmap(MI(ifp)->fbp, &(MI(ifp)->cmap));
433  MI(ifp)->cmap_dirty = 0;
434  }
435  if (MI(ifp)->mem_dirty) {
436  fb_writerect(MI(ifp)->fbp, 0, 0,
437  ifp->if_width, ifp->if_height, (unsigned char *)MI(ifp)->mem);
438  MI(ifp)->mem_dirty = 0;
439  }
440  return fb_flush(MI(ifp)->fbp);
441  }
442 
443  MI(ifp)->cmap_dirty = 0;
444  MI(ifp)->mem_dirty = 0;
445  return 0; /* success */
446 }
447 
448 
449 HIDDEN int
451 {
452  struct modeflags *mfp;
453 
454  fb_log("Description: %s\n", memory_interface.if_type);
455  fb_log("Device: %s\n", ifp->if_name);
456  fb_log("Max width/height: %d %d\n",
459  fb_log("Default width/height: %d %d\n",
462  fb_log("Usage: /dev/mem[options] [attached_framebuffer]\n");
463  for (mfp = modeflags; mfp->c != '\0'; mfp++) {
464  fb_log(" %c %s\n", mfp->c, mfp->help);
465  }
466  return 0;
467 }
468 
469 
470 /* This is the ONLY thing that we normally "export" */
472  0,
474  mem_open, /* device_open */
475  mem_open_existing, /* existing device_open */
476  mem_close_existing, /* existing device_close */
477  mem_get_fbps,
478  mem_put_fbps,
479  mem_close, /* device_close */
480  mem_clear, /* device_clear */
481  mem_read, /* buffer_read */
482  mem_write, /* buffer_write */
483  mem_rmap, /* colormap_read */
484  mem_wmap, /* colormap_write */
485  mem_view, /* set view */
486  mem_getview, /* get view */
487  mem_setcursor, /* define cursor */
488  mem_cursor, /* set cursor */
489  mem_getcursor, /* get cursor */
490  fb_sim_readrect, /* rectangle read */
491  fb_sim_writerect, /* rectangle write */
495  mem_refresh,
496  mem_poll, /* poll */
497  mem_flush, /* flush */
498  mem_close, /* free */
499  mem_help, /* help message */
500  "Memory Buffer", /* device description */
501  8192, /* max width */
502  8192, /* max height */
503  "/dev/mem", /* short device name */
504  512, /* default/current width */
505  512, /* default/current height */
506  -1, /* select fd */
507  -1, /* file descriptor */
508  1, 1, /* zoom */
509  256, 256, /* window center */
510  0, 0, 0, /* cursor */
511  PIXEL_NULL, /* page_base */
512  PIXEL_NULL, /* page_curp */
513  PIXEL_NULL, /* page_endp */
514  -1, /* page_no */
515  0, /* page_dirty */
516  0L, /* page_curpos */
517  0L, /* page_pixels */
518  0, /* debug */
519  0, /* refresh rate */
520  {0}, /* u1 */
521  {0}, /* u2 */
522  {0}, /* u3 */
523  {0}, /* u4 */
524  {0}, /* u5 */
525  {0} /* u6 */
526 };
527 
528 
529 /*
530  * Local Variables:
531  * mode: C
532  * tab-width: 8
533  * indent-tabs-mode: t
534  * c-file-style: "stroustrup"
535  * End:
536  * ex: shiftwidth=4 tabstop=8
537  */
ptrdiff_t ssize_t
Definition: common.h:119
#define COLORMAP_NULL
Definition: fb.h:91
unsigned char RGBpixel[3]
Definition: fb.h:73
HIDDEN int mem_setcursor(fb *ifp, const unsigned char *bits, int xbits, int ybits, int xorig, int yorig)
Definition: if_mem.c:382
void fb_log(const char *fmt,...) _BU_ATTR_PRINTF12
Definition: fb_log.c:42
HIDDEN int mem_getcursor(fb *ifp, int *mode, int *x, int *y)
Definition: if_mem.c:404
void fb_make_linear_cmap(ColorMap *cmap)
#define MODE_1MASK
Definition: if_mem.c:55
HIDDEN ssize_t mem_write(fb *ifp, int x, int y, const unsigned char *pixelp, size_t count)
Definition: if_mem.c:308
HIDDEN int mem_help(fb *ifp)
Definition: if_mem.c:450
#define RED
Definition: color.h:39
fb * fb_open(const char *file, int _width, int _height)
Definition: fb_generic.c:384
HIDDEN int mem_close(fb *ifp)
Definition: if_mem.c:227
#define FB_MEMORY_MAGIC
Definition: magic.h:189
#define PIXEL_NULL
Definition: fb.h:89
Header file for the BRL-CAD common definitions.
int fb_sim_bwreadrect(fb *ifp, int xmin, int ymin, int _width, int _height, unsigned char *pp)
Definition: fb_rect.c:102
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
HIDDEN int mem_refresh(fb *ifp, int x, int y, int w, int h)
Definition: if_mem.c:221
#define BLU
Definition: color.h:41
ustring width
int fb_cursor(fb *ifp, int mode, int x, int y)
Definition: fb_generic.c:300
#define HIDDEN
Definition: common.h:86
char * if_type
what "open" calls it
Definition: fb_private.h:110
int fb_sim_writerect(fb *ifp, int xmin, int ymin, int _width, int _height, const unsigned char *pp)
Definition: fb_rect.c:78
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
int fb_close(fb *ifp)
Definition: fb_generic.c:478
void * memset(void *s, int c, size_t n)
int if_selfd
select(fd) for input events if >= 0
Definition: fb_private.h:117
HIDDEN struct fb_platform_specific * mem_get_fbps(uint32_t magic)
Definition: if_mem.c:190
#define FB_CK_FB(_p)
Definition: fb.h:100
#define FB_NULL
Definition: fb.h:95
int fb_sim_getcursor(fb *ifp, int *mode, int *x, int *y)
Definition: fb_util.c:96
#define MIL(ptr)
Definition: if_mem.c:53
int fb_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
Definition: fb_generic.c:288
HIDDEN int mem_open(fb *ifp, const char *file, int width, int height)
Definition: if_mem.c:78
HIDDEN int mem_wmap(fb *ifp, const ColorMap *cmp)
Definition: if_mem.c:340
HIDDEN int mem_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
Definition: if_mem.c:370
#define MODE_2PREREAD
Definition: if_mem.c:61
#define MODE_1IMMEDIATE
Definition: if_mem.c:57
HIDDEN int mem_rmap(fb *ifp, ColorMap *cmp)
Definition: if_mem.c:332
int if_max_height
max device height
Definition: fb_private.h:112
int fb_sim_bwwriterect(fb *ifp, int xmin, int ymin, int _width, int _height, const unsigned char *pp)
Definition: fb_rect.c:132
oldeumate l2 magic
Definition: nmg_mod.c:3843
#define UNUSED(parameter)
Definition: common.h:239
unsigned char * mem
Definition: if_mem.c:46
int mem_dirty
Definition: if_mem.c:48
HIDDEN int mem_close_existing(fb *ifp)
Definition: if_mem.c:209
int fb_sim_cursor(fb *ifp, int mode, int x, int y)
Definition: fb_util.c:79
HIDDEN int mem_clear(fb *ifp, unsigned char *pp)
Definition: if_mem.c:251
#define RGBPIXEL_NULL
Definition: fb.h:90
int fb_readrect(fb *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
Definition: fb_generic.c:308
ustring alpha
HIDDEN void mem_put_fbps(struct fb_platform_specific *fbps)
Definition: if_mem.c:197
Definition: fb.h:82
int fb_rmap(fb *ifp, ColorMap *cmap)
Definition: fb_generic.c:280
HIDDEN int mem_open_existing(fb *ifp, int width, int height, struct fb_platform_specific *fb_p)
Definition: if_mem.c:203
int fb_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
Definition: fb_generic.c:292
ssize_t fb_write(fb *ifp, int x, int y, const unsigned char *pp, size_t count)
Definition: fb_generic.c:276
int fb_wmap(fb *ifp, const ColorMap *cmap)
Definition: fb_generic.c:284
#define MI(ptr)
Definition: if_mem.c:52
HIDDEN int mem_poll(fb *ifp)
Definition: if_mem.c:415
int fb_flush(fb *ifp)
int fb_sim_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
Definition: fb_util.c:61
int fb_clear(fb *ifp, unsigned char *pp)
Definition: fb_generic.c:268
int fb_sim_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
Definition: fb_util.c:43
#define MODE_2MASK
Definition: if_mem.c:59
fb memory_interface
Definition: if_mem.c:471
fb * fbp
Definition: if_mem.c:45
A frame-buffer IO structure.
Definition: fb_private.h:80
int if_width
current values
Definition: fb_private.h:115
ColorMap cmap
Definition: if_mem.c:47
HIDDEN int mem_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
Definition: if_mem.c:358
#define GRN
Definition: color.h:40
HIDDEN int mem_flush(fb *ifp)
Definition: if_mem.c:425
int write_thru
Definition: if_mem.c:50
int fb_sim_readrect(fb *ifp, int xmin, int ymin, int _width, int _height, unsigned char *pp)
Definition: fb_rect.c:45
HIDDEN int mem_cursor(fb *ifp, int mode, int x, int y)
Definition: if_mem.c:393
char * if_name
what the user called it
Definition: fb_private.h:114
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
int fb_poll(fb *ifp)
Definition: fb_generic.c:250
int cmap_dirty
Definition: if_mem.c:49
HIDDEN int mem_configure_window(fb *ifp, int width, int height)
Definition: if_mem.c:215
HIDDEN ssize_t mem_read(fb *ifp, int x, int y, unsigned char *pixelp, size_t count)
Definition: if_mem.c:289