BRL-CAD
if_disk.c
Go to the documentation of this file.
1 /* I F _ D I S K . 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 /** @addtogroup if */
21 /** @{ */
22 /** @file if_disk.c
23  *
24  */
25 /** @} */
26 
27 #include "common.h"
28 
29 #include "bu/color.h"
30 #include "bu/file.h"
31 #include "bu/log.h"
32 #include "bu/str.h"
33 #include "fb_private.h"
34 #include "fb.h"
35 
36 
37 #define FILE_CMAP_ADDR ((off_t) ifp->if_width*ifp->if_height \
38  *sizeof(RGBpixel))
39 
40 /* Ensure integer number of pixels per DMA */
41 #define DISK_DMA_BYTES ((size_t)16*(size_t)1024/sizeof(RGBpixel)*sizeof(RGBpixel))
42 #define DISK_DMA_PIXELS (DISK_DMA_BYTES/sizeof(RGBpixel))
43 
44 #define if_seekpos u5.l /* stored seek position */
45 
46 
47 HIDDEN int
48 dsk_open(fb *ifp, const char *file, int width, int height)
49 {
50  static char zero = 0;
51 
52  FB_CK_FB(ifp);
53 
54  /* check for default size */
55  if (width == 0)
56  width = ifp->if_width;
57  if (height == 0)
58  height = ifp->if_height;
59 
60  if (BU_STR_EQUAL(file, "-")) {
61  /*
62  * It is the applications job to write ascending scanlines.
63  * If it does not, then this can be stacked with /dev/mem,
64  * i.e. /dev/mem -
65  */
66  ifp->if_fd = 1; /* fileno(stdout) */
67  ifp->if_width = width;
68  ifp->if_height = height;
69  ifp->if_seekpos = 0;
70  return 0;
71  }
72 
73  if ((ifp->if_fd = open(file, O_RDWR | O_BINARY, 0)) == -1
74  && (ifp->if_fd = open(file, O_RDONLY | O_BINARY, 0)) == -1) {
75  if ((ifp->if_fd = open(file, O_RDWR | O_CREAT | O_BINARY, 0664)) > 0) {
76  /* New file, write byte at end */
77  if (lseek(ifp->if_fd, (height*width*sizeof(RGBpixel)-1), 0) == -1) {
78  fb_log("disk_device_open : can not seek to end of new file.\n");
79  return -1;
80  }
81  if (write(ifp->if_fd, &zero, 1) < 0) {
82  fb_log("disk_device_open : initial write failed.\n");
83  return -1;
84  }
85  } else
86  return -1;
87  }
88 
89  setmode(ifp->if_fd, O_BINARY);
90 
91  ifp->if_width = width;
92  ifp->if_height = height;
93  if (lseek(ifp->if_fd, 0, 0) == -1) {
94  fb_log("disk_device_open : can not seek to beginning.\n");
95  return -1;
96  }
97  ifp->if_seekpos = 0;
98  return 0;
99 }
100 
103 {
104  return NULL;
105 }
106 
107 
108 HIDDEN void
110 {
111  return;
112 }
113 
114 HIDDEN int
115 dsk_open_existing(fb *UNUSED(ifp), int UNUSED(width), int UNUSED(height), struct fb_platform_specific *UNUSED(fb_p))
116 {
117  return 0;
118 }
119 
120 HIDDEN int
122 {
123  return 0;
124 }
125 
126 HIDDEN int
127 dsk_configure_window(fb *UNUSED(ifp), int UNUSED(width), int UNUSED(height))
128 {
129  return 0;
130 }
131 
132 HIDDEN int
133 dsk_refresh(fb *UNUSED(ifp), int UNUSED(x), int UNUSED(y), int UNUSED(w), int UNUSED(h))
134 {
135  return 0;
136 }
137 
138 HIDDEN int
140 {
141  return close(ifp->if_fd);
142 }
143 
144 
145 HIDDEN int
147 {
148  close(ifp->if_fd);
149  if (bu_file_delete(ifp->if_name)) {
150  return 0;
151  } else {
152  return 1;
153  }
154 }
155 
156 
157 /*
158  * Clear the disk file to the given color.
159  */
160 HIDDEN int
161 disk_color_clear(fb *ifp, register unsigned char *bpp)
162 {
163  static unsigned char pix_buf[DISK_DMA_BYTES] = {0};
164  register unsigned char *pix_to;
165  size_t i;
166  int fd;
167  size_t pixelstodo;
168 
169  /* Fill buffer with background color. */
170  for (i = DISK_DMA_PIXELS, pix_to = pix_buf; i > 0; i--) {
171  COPYRGB(pix_to, bpp);
172  pix_to += sizeof(RGBpixel);
173  }
174 
175  /* Set start of framebuffer */
176  fd = ifp->if_fd;
177  if (ifp->if_seekpos != 0 && lseek(fd, 0, 0) == -1) {
178  fb_log("disk_color_clear : seek failed.\n");
179  return -1;
180  }
181 
182  /* Send until frame buffer is full. */
183  pixelstodo = ifp->if_height * ifp->if_width;
184  while (pixelstodo > 0) {
185  i = pixelstodo > DISK_DMA_PIXELS ? DISK_DMA_PIXELS : pixelstodo;
186  if (write(fd, pix_buf, i * sizeof(RGBpixel)) == -1)
187  return -1;
188  pixelstodo -= i;
189  ifp->if_seekpos += i * sizeof(RGBpixel);
190  }
191 
192  return 0;
193 }
194 
195 
196 HIDDEN int
197 dsk_clear(fb *ifp, unsigned char *bgpp)
198 {
199  static RGBpixel black = { 0, 0, 0 };
200 
201  if (bgpp == (unsigned char *)NULL)
202  return disk_color_clear(ifp, black);
203 
204  return disk_color_clear(ifp, bgpp);
205 }
206 
207 
209 dsk_read(fb *ifp, int x, int y, unsigned char *pixelp, size_t count)
210 {
211  size_t bytes = count * sizeof(RGBpixel);
212  size_t todo;
213  ssize_t got;
214  size_t dest;
215  size_t bytes_read = 0;
216  int fd = ifp->if_fd;
217 
218  /* Reads on stdout make no sense. Take reads from stdin. */
219  if (fd == 1) fd = 0;
220 
221  dest = ((y * ifp->if_width) + x) * sizeof(RGBpixel);
222  if (ifp->if_seekpos != dest && lseek(fd, dest, 0) == -1) {
223  fb_log("disk_buffer_read : seek to %ld failed.\n", dest);
224  return -1;
225  }
226  ifp->if_seekpos = dest;
227  while (bytes > 0) {
228  todo = bytes;
229  if ((got = read(fd, (char *) pixelp, todo)) != (ssize_t)todo) {
230  if (got <= 0) {
231  if (got < 0) {
232  perror("READ ERROR");
233  }
234 
235  if (bytes_read <= 0)
236  return -1; /* error */
237 
238  /* early EOF -- indicate what we got */
239  return bytes_read/sizeof(RGBpixel);
240  }
241  if (fd != 0) {
242  /* This happens all the time reading from pipes */
243  fb_log("disk_buffer_read(fd=%d): y=%d read of %lu got %ld bytes\n",
244  fd, y, todo, got);
245  }
246  }
247  bytes -= got;
248  pixelp += got;
249  ifp->if_seekpos += got;
250  bytes_read += got;
251  }
252  return bytes_read/sizeof(RGBpixel);
253 }
254 
255 
257 dsk_write(fb *ifp, int x, int y, const unsigned char *pixelp, size_t count)
258 {
259  register ssize_t bytes = count * sizeof(RGBpixel);
260  ssize_t todo;
261  off_t dest;
262 
263  dest = (y * ifp->if_width + x) * sizeof(RGBpixel);
264  if (dest != (off_t)ifp->if_seekpos) {
265  if (lseek(ifp->if_fd, dest, 0) == -1) {
266  fb_log("disk_buffer_write : seek to %ld failed.\n", dest);
267  return -1;
268  }
269  ifp->if_seekpos = dest;
270  }
271  while (bytes > 0) {
272  ssize_t ret;
273  todo = bytes;
274  ret = write(ifp->if_fd, (char *) pixelp, todo);
275  if (ret != todo) {
276  fb_log("disk_buffer_write: write failed\n");
277  return -1;
278  }
279  bytes -= todo;
280  pixelp += todo / sizeof(RGBpixel);
281  ifp->if_seekpos += todo;
282  }
283  return count;
284 }
285 
286 
287 HIDDEN int
288 dsk_rmap(fb *ifp, ColorMap *cmap)
289 {
290  int fd = ifp->if_fd;
291 
292  /* Reads on stdout make no sense. Take reads from stdin. */
293  if (fd == 1) fd = 0;
294 
295  if (ifp->if_seekpos != FILE_CMAP_ADDR &&
296  lseek(fd, FILE_CMAP_ADDR, 0) == -1) {
297  fb_log("disk_colormap_read : seek to %ld failed.\n",
299  return -1;
300  }
301  if (read(fd, (char *) cmap, sizeof(ColorMap)) != sizeof(ColorMap)) {
302  /* Not necessarily an error. It is not required that a
303  * color map be saved and the standard map is not
304  * generally saved.
305  */
306  return -1;
307  }
308  return 0;
309 }
310 
311 
312 HIDDEN int
313 dsk_wmap(fb *ifp, const ColorMap *cmap)
314 {
315  if (cmap == (ColorMap *) NULL)
316  /* Do not write default map to file. */
317  return 0;
318  if (fb_is_linear_cmap(cmap))
319  return 0;
320  if (lseek(ifp->if_fd, FILE_CMAP_ADDR, 0) == -1) {
321  fb_log("disk_colormap_write : seek to %ld failed.\n",
323  return -1;
324  }
325  if (write(ifp->if_fd, (char *) cmap, sizeof(ColorMap))
326  != sizeof(ColorMap)) {
327  fb_log("disk_colormap_write : write failed.\n");
328  return -1;
329  }
330  return 0;
331 }
332 
333 
334 HIDDEN int
336 {
337  fb_log("Description: %s\n", disk_interface.if_type);
338  fb_log("Device: %s\n", ifp->if_name);
339  fb_log("Max width/height: %d %d\n",
342  fb_log("Default width/height: %d %d\n",
345  if (ifp->if_fd == 1) {
346  fb_log("File \"-\" reads from stdin, writes to stdout\n");
347  } else {
348  fb_log("Note: you may have just created a disk file\n");
349  fb_log("called \"%s\" by running this.\n", ifp->if_name);
350  }
351 
352  return 0;
353 }
354 
355 
357  0,
359  dsk_open,
362  dsk_get_fbps,
363  dsk_put_fbps,
364  dsk_close,
365  dsk_clear,
366  dsk_read,
367  dsk_write,
368  dsk_rmap,
369  dsk_wmap,
370  fb_sim_view, /* set view */
371  fb_sim_getview, /* get view */
372  fb_null_setcursor, /* define cursor */
373  fb_sim_cursor, /* set cursor */
374  fb_sim_getcursor, /* get cursor */
380  dsk_refresh,
381  fb_null, /* poll */
382  fb_null, /* flush */
383  dsk_free,
384  dsk_help,
385  "Disk File Interface",
386  32*1024, /* the sky's really the limit here */
387  32*1024,
388  "filename", /* not in list so name is safe */
389  512,
390  512,
391  -1, /* select fd */
392  -1,
393  1, 1, /* zoom */
394  256, 256, /* window center */
395  0, 0, 0, /* cursor */
396  PIXEL_NULL,
397  PIXEL_NULL,
398  PIXEL_NULL,
399  -1,
400  0,
401  0L,
402  0L,
403  0, /* debug */
404  0, /* refresh rate */
405  {0}, /* u1 */
406  {0}, /* u2 */
407  {0}, /* u3 */
408  {0}, /* u4 */
409  {0}, /* u5 */
410  {0} /* u6 */
411 };
412 
413 
414 /*
415  * Local Variables:
416  * mode: C
417  * tab-width: 8
418  * indent-tabs-mode: t
419  * c-file-style: "stroustrup"
420  * End:
421  * ex: shiftwidth=4 tabstop=8
422  */
ptrdiff_t ssize_t
Definition: common.h:119
unsigned char RGBpixel[3]
Definition: fb.h:73
void fb_log(const char *fmt,...) _BU_ATTR_PRINTF12
Definition: fb_log.c:42
int if_fd
internal file descriptor
Definition: fb_private.h:119
HIDDEN int dsk_wmap(fb *ifp, const ColorMap *cmap)
Definition: if_disk.c:313
#define FILE_CMAP_ADDR
Definition: if_disk.c:37
HIDDEN int dsk_free(fb *ifp)
Definition: if_disk.c:146
int fb_null(fb *ifp)
Definition: fb_generic.c:359
#define DISK_DMA_BYTES
Definition: if_disk.c:41
HIDDEN int dsk_refresh(fb *ifp, int x, int y, int w, int h)
Definition: if_disk.c:133
HIDDEN int dsk_open_existing(fb *ifp, int width, int height, struct fb_platform_specific *fb_p)
Definition: if_disk.c:115
#define PIXEL_NULL
Definition: fb.h:89
HIDDEN ssize_t dsk_read(fb *ifp, int x, int y, unsigned char *pixelp, size_t count)
Definition: if_disk.c:209
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_is_linear_cmap(const ColorMap *cmap)
int if_max_width
max device width
Definition: fb_private.h:111
ustring width
#define COPYRGB(to, from)
Definition: fb.h:191
#define HIDDEN
Definition: common.h:86
char * if_type
what "open" calls it
Definition: fb_private.h:110
HIDDEN int dsk_clear(fb *ifp, unsigned char *bgpp)
Definition: if_disk.c:197
int fb_sim_writerect(fb *ifp, int xmin, int ymin, int _width, int _height, const unsigned char *pp)
Definition: fb_rect.c:78
HIDDEN int dsk_close(fb *ifp)
Definition: if_disk.c:139
#define FB_CK_FB(_p)
Definition: fb.h:100
int fb_sim_getcursor(fb *ifp, int *mode, int *x, int *y)
Definition: fb_util.c:96
HIDDEN struct fb_platform_specific * dsk_get_fbps(uint32_t magic)
Definition: if_disk.c:102
HIDDEN int dsk_close_existing(fb *ifp)
Definition: if_disk.c:121
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
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 DISK_DMA_PIXELS
Definition: if_disk.c:42
#define UNUSED(parameter)
Definition: common.h:239
int fb_sim_cursor(fb *ifp, int mode, int x, int y)
Definition: fb_util.c:79
#define FB_DISK_MAGIC
Definition: magic.h:187
Definition: fb.h:82
HIDDEN int disk_color_clear(fb *ifp, register unsigned char *bpp)
Definition: if_disk.c:161
fb disk_interface
Definition: if_disk.c:356
HIDDEN int dsk_open(fb *ifp, const char *file, int width, int height)
Definition: if_disk.c:48
int fb_sim_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
Definition: fb_util.c:61
HIDDEN ssize_t dsk_write(fb *ifp, int x, int y, const unsigned char *pixelp, size_t count)
Definition: if_disk.c:257
int fb_sim_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
Definition: fb_util.c:43
Definition: human.c:197
A frame-buffer IO structure.
Definition: fb_private.h:80
int if_width
current values
Definition: fb_private.h:115
HIDDEN int dsk_configure_window(fb *ifp, int width, int height)
Definition: if_disk.c:127
int fb_sim_readrect(fb *ifp, int xmin, int ymin, int _width, int _height, unsigned char *pp)
Definition: fb_rect.c:45
char * if_name
what the user called it
Definition: fb_private.h:114
HIDDEN void dsk_put_fbps(struct fb_platform_specific *fbps)
Definition: if_disk.c:109
HIDDEN int dsk_help(fb *ifp)
Definition: if_disk.c:335
HIDDEN int dsk_rmap(fb *ifp, ColorMap *cmap)
Definition: if_disk.c:288
int bu_file_delete(const char *path)
Definition: file.c:278
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126