BRL-CAD
if_osgl.cpp
Go to the documentation of this file.
1 /* I F _ O S G L . C P P
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_osgl.cpp
23  *
24  * An OpenGL framebuffer using OpenSceneGraph.
25  *
26  * There are several different Frame Buffer modes supported. Set your
27  * environment FB_FILE to the appropriate type.
28  *
29  * (see the modeflag definitions below). /dev/osgl[options]
30  *
31  * This code is basically a port of the 4d Framebuffer interface from
32  * IRIS GL to OpenGL, using OpenSceneGraph for portability.
33  *
34  */
35 /** @} */
36 
37 
38 #ifdef IF_OSGL
39 
40 #include "common.h"
41 extern "C" {
42 #include "fb_private.h"
43 }
44 #include "fb/fb_osgl.h"
45 
46 #include <osg/GLExtensions>
47 
48 #define CJDEBUG 0
49 #define DIRECT_COLOR_VISUAL_ALLOWED 0
50 
51 /* XXX - arbitrary upper bound */
52 #define XMAXSCREEN 16383
53 #define YMAXSCREEN 16383
54 
55 HIDDEN int osgl_nwindows = 0; /* number of open windows */
56 /*HIDDEN XColor color_cell[256];*/ /* used to set colormap */
57 
58 
59 /*
60  * Structure of color map in shared memory region. Has exactly the
61  * same format as the SGI hardware "gammaramp" map Note that only the
62  * lower 8 bits are significant.
63  */
64 struct osgl_cmap {
65  short cmr[256];
66  short cmg[256];
67  short cmb[256];
68 };
69 
70 
71 /*
72  * This defines the format of the in-memory framebuffer copy. The
73  * alpha component and reverse order are maintained for compatibility
74  * with /dev/sgi
75  */
76 struct osgl_pixel {
77  unsigned char blue;
78  unsigned char green;
79  unsigned char red;
80  unsigned char alpha;
81 };
82 
83 
84 /* Clipping structure for zoom/pan operations */
85 struct osgl_clip {
86  int xpixmin; /* view clipping planes clipped to pixel memory space*/
87  int xpixmax;
88  int ypixmin;
89  int ypixmax;
90  int xscrmin; /* view clipping planes */
91  int xscrmax;
92  int yscrmin;
93  int yscrmax;
94  double oleft; /* glOrtho parameters */
95  double oright;
96  double otop;
97  double obottom;
98 
99 };
100 
101 
102 /*
103  * Per window state information, overflow area.
104  */
105 struct sgiinfo {
106  short mi_cmap_flag; /* enabled when there is a non-linear map in memory */
107  int mi_shmid;
108  int mi_memwidth; /* width of scanline in if_mem */
109  short mi_xoff; /* X viewport offset, rel. window*/
110  short mi_yoff; /* Y viewport offset, rel. window*/
111  int mi_pid; /* for multi-cpu check */
112  int mi_parent; /* PID of linger-mode process */
113  struct osgl_pixel mi_scanline[XMAXSCREEN+1]; /* one scanline */
114 };
115 
116 
117 /*
118  * Per window state information particular to the OpenGL interface
119  */
120 struct osglinfo {
121  osgViewer::Viewer *viewer;
122  osg::Image *image;
123  osg::TextureRectangle *texture;
124  osg::Geometry *pictureQuad;
125  osg::Group *root;
126  osg::Timer *timer;
127  int last_update_time;
128  int cursor_on;
129  int use_texture;
130 
131  osg::GraphicsContext *glc;
132  osg::GraphicsContext::Traits *traits;
133  int firstTime;
134  int alive;
135  long event_mask; /* event types to be received */
136  int cmap_size; /* hardware colormap size */
137  int win_width; /* actual window width */
138  int win_height; /* actual window height */
139  int vp_width; /* actual viewport width */
140  int vp_height; /* actual viewport height */
141  struct osgl_clip clip; /* current view clipping */
142  /*Window cursor;*/
143  /*XVisualInfo *vip;*/ /* pointer to info on current visual */
144  /*Colormap xcmap;*/ /* xstyle color map */
145  int use_ext_ctrl; /* for controlling the Ogl graphics engine externally */
146 };
147 
148 
149 #define SGI(ptr) ((struct sgiinfo *)((ptr)->u1.p))
150 #define SGIL(ptr) ((ptr)->u1.p) /* left hand side version */
151 #define OSGL(ptr) ((struct osglinfo *)((ptr)->u6.p))
152 #define OSGLL(ptr) ((ptr)->u6.p) /* left hand side version */
153 #define if_mem u2.p /* shared memory pointer */
154 #define if_cmap u3.p /* color map in shared memory */
155 #define CMR(x) ((struct osgl_cmap *)((x)->if_cmap))->cmr
156 #define CMG(x) ((struct osgl_cmap *)((x)->if_cmap))->cmg
157 #define CMB(x) ((struct osgl_cmap *)((x)->if_cmap))->cmb
158 #define if_zoomflag u4.l /* zoom > 1 */
159 #define if_mode u5.l /* see MODE_* defines */
160 
161 #define MARGIN 4 /* # pixels margin to screen edge */
162 
163 #define CLIP_XTRA 1
164 
165 #define WIN_L (ifp->if_max_width - ifp->if_width - MARGIN)
166 #define WIN_T (ifp->if_max_height - ifp->if_height - MARGIN)
167 
168 /*
169  * The mode has several independent bits:
170  *
171  * SHARED -vs- MALLOC'ed memory for the image
172  * TRANSIENT -vs- LINGERING windows
173  * Windowed -vs- Centered Full screen
174  * Suppress dither -vs- dither
175  * DrawPixels -vs- CopyPixels
176  */
177 #define MODE_1MASK (1<<0)
178 #define MODE_1SHARED (0<<0) /* Use Shared memory */
179 #define MODE_1MALLOC (1<<0) /* Use malloc memory */
180 
181 #define MODE_2MASK (1<<1)
182 #define MODE_2TRANSIENT (0<<1)
183 #define MODE_2LINGERING (1<<1) /* leave window up after closing*/
184 
185 #define MODE_4MASK (1<<3)
186 #define MODE_4NORMAL (0<<3) /* dither if it seems necessary */
187 #define MODE_4NODITH (1<<3) /* suppress any dithering */
188 
189 #define MODE_7MASK (1<<6)
190 #define MODE_7NORMAL (0<<6) /* install colormap in hardware if possible*/
191 #define MODE_7SWCMAP (1<<6) /* use software colormapping */
192 
193 /* and copy current view to front */
194 #define MODE_15MASK (1<<14)
195 #define MODE_15NORMAL (0<<14)
196 #define MODE_15ZAP (1<<14) /* zap the shared memory segment */
197 #if 0
198 HIDDEN struct modeflags {
199  const char c;
200  long mask;
201  long value;
202  const char *help;
203 } modeflags[] = {
204  { 'p', MODE_1MASK, MODE_1MALLOC,
205  "Private memory - else shared" },
206  { 'l', MODE_2MASK, MODE_2LINGERING,
207  "Lingering window" },
208  { 't', MODE_2MASK, MODE_2TRANSIENT,
209  "Transient window" },
210  { 'd', MODE_4MASK, MODE_4NODITH,
211  "Suppress dithering - else dither if not 24-bit buffer" },
212  { 'c', MODE_7MASK, MODE_7SWCMAP,
213  "Perform software colormap - else use hardware colormap if possible" },
214  { 'z', MODE_15MASK, MODE_15ZAP,
215  "Zap (free) shared memory. Can also be done with fbfree command" },
216  { '\0', 0, 0, "" }
217 };
218 #endif
219 
220 /* OpenSceneGraph interactions for a framebuffer viewer */
221 #include "osg_fb_manipulator.h"
222 
223 /*
224  * Note: unlike sgi_xmit_scanlines, this function updates an arbitrary
225  * rectangle of the frame buffer
226  */
227 HIDDEN void
228 osgl_xmit_scanlines(register fb *ifp, int ybase, int nlines, int xbase, int npix)
229 {
230  register int y;
231  register int n;
232  int sw_cmap; /* !0 => needs software color map */
233  struct osgl_clip *clp;
234 
235  /* Caller is expected to handle attaching context, etc. */
236 
237  clp = &(OSGL(ifp)->clip);
238 
239  if (SGI(ifp)->mi_cmap_flag) {
240  sw_cmap = 1;
241  } else {
242  sw_cmap = 0;
243  }
244 
245  if (xbase > clp->xpixmax || ybase > clp->ypixmax)
246  return;
247  if (xbase < clp->xpixmin)
248  xbase = clp->xpixmin;
249  if (ybase < clp->ypixmin)
250  ybase = clp->ypixmin;
251 
252  if ((xbase + npix -1) > clp->xpixmax)
253  npix = clp->xpixmax - xbase + 1;
254  if ((ybase + nlines - 1) > clp->ypixmax)
255  nlines = clp->ypixmax - ybase + 1;
256 
257  if (!OSGL(ifp)->use_ext_ctrl) {
258  /*
259  * Blank out areas of the screen around the image, if
260  * exposed. In COPY mode, this is done in
261  * backbuffer_to_screen().
262  */
263 
264  /* Blank out area left of image */
265  glColor3b(0, 0, 0);
266  if (clp->xscrmin < 0) glRecti(clp->xscrmin - CLIP_XTRA,
267  clp->yscrmin - CLIP_XTRA,
268  CLIP_XTRA,
269  clp->yscrmax + CLIP_XTRA);
270 
271  /* Blank out area below image */
272  if (clp->yscrmin < 0) glRecti(clp->xscrmin - CLIP_XTRA,
273  clp->yscrmin - CLIP_XTRA,
274  clp->xscrmax + CLIP_XTRA,
275  CLIP_XTRA);
276 
277  /* Blank out area right of image */
278  if (clp->xscrmax >= ifp->if_width) glRecti(ifp->if_width - CLIP_XTRA,
279  clp->yscrmin - CLIP_XTRA,
280  clp->xscrmax + CLIP_XTRA,
281  clp->yscrmax + CLIP_XTRA);
282 
283  /* Blank out area above image */
284  if (clp->yscrmax >= ifp->if_height) glRecti(clp->xscrmin - CLIP_XTRA,
285  ifp->if_height- CLIP_XTRA,
286  clp->xscrmax + CLIP_XTRA,
287  clp->yscrmax + CLIP_XTRA);
288 
289  }
290 
291  if (sw_cmap) {
292  /* Software colormap each line as it's transmitted */
293  register int x;
294  register struct osgl_pixel *osglp;
295  register struct osgl_pixel *op;
296 
297  y = ybase;
298  if (CJDEBUG) printf("Doing sw colormap xmit\n");
299  /* Perform software color mapping into temp scanline */
300  op = SGI(ifp)->mi_scanline;
301  for (n=nlines; n>0; n--, y++) {
302  if (!OSGL(ifp)->viewer) {
303  osglp = (struct osgl_pixel *)&ifp->if_mem[(y*SGI(ifp)->mi_memwidth)*sizeof(struct osgl_pixel) ];
304  } else {
305  osglp = (struct osgl_pixel *)(OSGL(ifp)->image->data(0,y,0));
306  }
307  for (x=xbase+npix-1; x>=xbase; x--) {
308  op[x].red = CMR(ifp)[osglp[x].red];
309  op[x].green = CMG(ifp)[osglp[x].green];
310  op[x].blue = CMB(ifp)[osglp[x].blue];
311  }
312 
313  glPixelStorei(GL_UNPACK_SKIP_PIXELS, xbase);
314  glRasterPos2i(xbase, y);
315  glDrawPixels(npix, 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
316  (const GLvoid *) op);
317 
318  }
319 
320  } else {
321  /* No need for software colormapping */
322  glPixelStorei(GL_UNPACK_ROW_LENGTH, SGI(ifp)->mi_memwidth);
323  glPixelStorei(GL_UNPACK_SKIP_PIXELS, xbase);
324  glPixelStorei(GL_UNPACK_SKIP_ROWS, ybase);
325 
326  glRasterPos2i(xbase, ybase);
327  glDrawPixels(npix, nlines, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
328  (const GLvoid *) ifp->if_mem);
329  }
330 }
331 
332 
333 HIDDEN void
334 osgl_cminit(register fb *ifp)
335 {
336  register int i;
337 
338  for (i = 0; i < 256; i++) {
339  CMR(ifp)[i] = i;
340  CMG(ifp)[i] = i;
341  CMB(ifp)[i] = i;
342  }
343 }
344 
345 
346 /******************* Shared Memory Support ******************************/
347 HIDDEN int
348 osgl_getmem(fb *ifp)
349 {
350  int shm_result;
351  int pixsize;
352  int size;
353  int i;
354  char *sp;
355  int new_mem = 0;
356 
357  errno = 0;
358 
359 #ifdef HAVE_SYS_SHM_H
360  if ((ifp->if_mode & MODE_1MASK) == MODE_1MALLOC)
361 #endif
362  {
363  /*
364  * In this mode, only malloc as much memory as is needed.
365  */
366  SGI(ifp)->mi_memwidth = ifp->if_width;
367  pixsize = ifp->if_height * ifp->if_width * sizeof(struct osgl_pixel);
368  size = pixsize + sizeof(struct osgl_cmap);
369 
370  sp = (char *)calloc(1, size);
371  if (sp == 0) {
372  fb_log("osgl_getmem: frame buffer memory malloc failed\n");
373  goto fail;
374  }
375  new_mem = 1;
376  goto success;
377  }
378 
379 #ifdef HAVE_SYS_SHM_H
380  /* The shared memory section never changes size */
381  SGI(ifp)->mi_memwidth = ifp->if_max_width;
382 
383  /*
384  * On some platforms lrectwrite() runs off the end! So, provide a
385  * pad area of 2 scanlines. (1 line is enough, but this avoids
386  * risk of damage to colormap table.)
387  */
388  pixsize = (ifp->if_max_height+2) * ifp->if_max_width *
389  sizeof(struct osgl_pixel);
390 
391  size = pixsize + sizeof(struct osgl_cmap);
392 
393 
394  shm_result = bu_shmget(&(SGI(ifp)->mi_shmid), &sp, SHMEM_KEY, (size_t)size);
395 
396  if (shm_result == 1) goto fail;
397  if (shm_result == -1) new_mem = 1;
398 #endif
399 
400 success:
401  ifp->if_mem = sp;
402  ifp->if_cmap = sp + pixsize; /* cmap at end of area */
403  i = CMB(ifp)[255]; /* try to deref last word */
404  CMB(ifp)[255] = i;
405 
406  /* Provide non-black colormap on creation of new shared mem */
407  if (new_mem)
408  osgl_cminit(ifp);
409  return 0;
410 fail:
411 #ifdef HAVE_SYS_SHM_H
412  fb_log("osgl_getmem: Unable to attach to shared memory.\n");
413 #endif
414  if ((sp = (char *)calloc(1, size)) == NULL) {
415  fb_log("osgl_getmem: malloc failure\n");
416  return -1;
417  }
418  new_mem = 1;
419  goto success;
420 }
421 
422 
423 void
424 osgl_zapmem(void)
425 {
426 #ifdef HAVE_SYS_SHM_H
427  int shmid;
428  int i;
429 
430  if ((shmid = shmget(SHMEM_KEY, 0, 0)) < 0) {
431  fb_log("osgl_zapmem shmget failed, errno=%d\n", errno);
432  return;
433  }
434 
435  i = shmctl(shmid, IPC_RMID, 0);
436  if (i < 0) {
437  fb_log("osgl_zapmem shmctl failed, errno=%d\n", errno);
438  return;
439  }
440  fb_log("if_osgl: shared memory released\n");
441 #endif
442 }
443 
444 
445 /**
446  * Given:- the size of the viewport in pixels (vp_width, vp_height)
447  * - the size of the framebuffer image (if_width, if_height)
448  * - the current view center (if_xcenter, if_ycenter)
449  * - the current zoom (if_xzoom, if_yzoom)
450  * Calculate:
451  * - the position of the viewport in image space
452  * (xscrmin, xscrmax, yscrmin, yscrmax)
453  * - the portion of the image which is visible in the viewport
454  * (xpixmin, xpixmax, ypixmin, ypixmax)
455  */
456 void
457 osgl_clipper(register fb *ifp)
458 {
459  register struct osgl_clip *clp;
460  register int i;
461  double pixels;
462 
463  clp = &(OSGL(ifp)->clip);
464 
465  i = OSGL(ifp)->vp_width/(2*ifp->if_xzoom);
466  clp->xscrmin = ifp->if_xcenter - i;
467  i = OSGL(ifp)->vp_width/ifp->if_xzoom;
468  clp->xscrmax = clp->xscrmin + i;
469  pixels = (double) i;
470  clp->oleft = ((double) clp->xscrmin) - 0.25*pixels/((double) OSGL(ifp)->vp_width);
471  clp->oright = clp->oleft + pixels;
472 
473  i = OSGL(ifp)->vp_height/(2*ifp->if_yzoom);
474  clp->yscrmin = ifp->if_ycenter - i;
475  i = OSGL(ifp)->vp_height/ifp->if_yzoom;
476  clp->yscrmax = clp->yscrmin + i;
477  pixels = (double) i;
478  clp->obottom = ((double) clp->yscrmin) - 0.25*pixels/((double) OSGL(ifp)->vp_height);
479  clp->otop = clp->obottom + pixels;
480 
481  clp->xpixmin = clp->xscrmin;
482  clp->xpixmax = clp->xscrmax;
483  clp->ypixmin = clp->yscrmin;
484  clp->ypixmax = clp->yscrmax;
485 
486  if (clp->xpixmin < 0) {
487  clp->xpixmin = 0;
488  }
489 
490  if (clp->ypixmin < 0) {
491  clp->ypixmin = 0;
492  }
493 
494  if (clp->xpixmax > ifp->if_width-1) {
495  clp->xpixmax = ifp->if_width-1;
496  }
497  if (clp->ypixmax > ifp->if_height-1) {
498  clp->ypixmax = ifp->if_height-1;
499  }
500  }
501 
502 int
503 osgl_configureWindow(fb *ifp, int width, int height)
504 {
505  if (width == OSGL(ifp)->win_width &&
506  height == OSGL(ifp)->win_height)
507  return 1;
508 
509  ifp->if_width = ifp->if_max_width = width;
510  ifp->if_height = ifp->if_max_height = height;
511 
512  OSGL(ifp)->win_width = OSGL(ifp)->vp_width = width;
513  OSGL(ifp)->win_height = OSGL(ifp)->vp_height = height;
514 
515  ifp->if_zoomflag = 0;
516  ifp->if_xzoom = 1;
517  ifp->if_yzoom = 1;
518  ifp->if_xcenter = width/2;
519  ifp->if_ycenter = height/2;
520 
521  osgl_getmem(ifp);
522  osgl_clipper(ifp);
523 
524  glViewport(0, 0, OSGL(ifp)->win_width, OSGL(ifp)->win_height);
525  return 0;
526 }
527 
528 
529 HIDDEN void
530 osgl_do_event(fb *ifp)
531 {
532  if (OSGL(ifp)->firstTime) {
533  OSGL(ifp)->firstTime = 0;
534  }
535 
536  if (OSGL(ifp)->viewer)
537  (*OSGL(ifp)->viewer).frame();
538 }
539 
540 /**
541  * Check for a color map being linear in R, G, and B. Returns 1 for
542  * linear map, 0 for non-linear map (i.e., non-identity map).
543  */
544 HIDDEN int
545 is_linear_cmap(register fb *ifp)
546 {
547  register int i;
548 
549  for (i = 0; i < 256; i++) {
550  if (CMR(ifp)[i] != i) return 0;
551  if (CMG(ifp)[i] != i) return 0;
552  if (CMB(ifp)[i] != i) return 0;
553  }
554  return 1;
555 }
556 
557 
558 HIDDEN int
559 fb_osgl_open(fb *ifp, const char *UNUSED(file), int width, int height)
560 {
561  FB_CK_FB(ifp);
562 
563  ifp->if_mode = MODE_2LINGERING;
564 
565  if ((SGIL(ifp) = (char *)calloc(1, sizeof(struct sgiinfo))) == NULL) {
566  fb_log("fb_osgl_open: sgiinfo malloc failed\n");
567  return -1;
568  }
569  if ((ifp->u6.p = (char *)calloc(1, sizeof(struct osglinfo))) == NULL) {
570  fb_log("fb_osgl_open: osglinfo malloc failed\n");
571  return -1;
572  }
573 
574  /* use defaults if invalid width and height specified */
575  if (width > 0)
576  ifp->if_width = width;
577  if (height > 0)
578  ifp->if_height = height;
579 
580  /* use max values if width and height are greater */
581  if (width > ifp->if_max_width)
582  ifp->if_width = ifp->if_max_width;
583  if (height > ifp->if_max_height)
584  ifp->if_height = ifp->if_max_height;
585 
586  /* initialize window state variables before calling osgl_getmem */
587  ifp->if_zoomflag = 0;
588  ifp->if_xzoom = 1; /* for zoom fakeout */
589  ifp->if_yzoom = 1; /* for zoom fakeout */
590  ifp->if_xcenter = width/2;
591  ifp->if_ycenter = height/2;
592  SGI(ifp)->mi_pid = bu_process_id();
593 
594  /* Attach to shared memory, potentially with a screen repaint */
595  if (osgl_getmem(ifp) < 0)
596  return -1;
597 
598  /* Make sure OpenSceneGraph knows to look in the root lib directory */
599  /* TODO - The OpenSceneGraph logic for handling plugins isn't multi-config
600  * aware - we're going to have to add that to make this mechanism work on Windows */
601  {
602  std::string rel_path = std::string(bu_brlcad_dir("lib", 0)) + std::string("/osgPlugins");
603  const char *root_path = bu_brlcad_root(rel_path.c_str(), 0);
604  osgDB::FilePathList paths = osgDB::Registry::instance()->getLibraryFilePathList();
605  if (root_path) {
606  std::string libpathstring(root_path);
607  /* The first entry is the final installed path - prefer that to the local
608  * bu_brlcad_root lib directory. This means our new path should be the
609  * second entry in the list - insert it accordingly. */
610  osgDB::FilePathList::iterator in_itr=++(paths.begin());
611  paths.insert(in_itr, libpathstring);
612  osgDB::Registry::instance()->setLibraryFilePathList(paths);
613  }
614  //for(osgDB::FilePathList::const_iterator libpath=osgDB::Registry::instance()->getLibraryFilePathList().begin(); libpath!=osgDB::Registry::instance()->getLibraryFilePathList().end(); ++libpath) std::cout << *libpath << "\n";
615  }
616 
617 
618  OSGL(ifp)->timer = new osg::Timer;
619  OSGL(ifp)->last_update_time = 0;
620 
621  OSGL(ifp)->viewer = new osgViewer::Viewer();
622  int woffset = 40;
623  osgViewer::SingleWindow *sw = new osgViewer::SingleWindow(0+woffset, 0+woffset, ifp->if_width, ifp->if_height);
624  OSGL(ifp)->viewer->apply(sw);
625  osg::Camera *camera = OSGL(ifp)->viewer->getCamera();
626  camera->setClearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
627  camera->setViewMatrix(osg::Matrix::identity());
628 
629  OSGL(ifp)->root = new osg::Group;
630  OSGL(ifp)->viewer->setSceneData(OSGL(ifp)->root);
631 
632  /* Need to realize and render a frame before we inquire what GL extensions are supported,
633  * or Bad Things happen to the OpenGL state */
634  OSGL(ifp)->use_texture = 0;
635  OSGL(ifp)->viewer->realize();
636  OSGL(ifp)->viewer->frame();
637  OSGL(ifp)->glc = camera->getGraphicsContext();
638  unsigned int contextID = OSGL(ifp)->glc->getState()->getContextID();
639  bool have_pixbuff = osg::isGLExtensionSupported(contextID, "GL_ARB_pixel_buffer_object");
640  if (have_pixbuff) {
641  std::cout << "Have GL_ARB_pixel_buffer_object\n";
642  }
643 
644  OSGL(ifp)->image = new osg::Image;
645  OSGL(ifp)->image->setImage(ifp->if_width, ifp->if_height, 1, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)ifp->if_mem, osg::Image::NO_DELETE);
646  OSGL(ifp)->image->setPixelBufferObject(new osg::PixelBufferObject(OSGL(ifp)->image));
647  OSGL(ifp)->pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f),
648  osg::Vec3(ifp->if_width,0.0f,0.0f), osg::Vec3(0.0f,0.0f, ifp->if_height), 0.0f, 0.0, OSGL(ifp)->image->s(), OSGL(ifp)->image->t());
649  OSGL(ifp)->texture = new osg::TextureRectangle(OSGL(ifp)->image);
650  /*OSGL(ifp)->texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
651  OSGL(ifp)->texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
652  OSGL(ifp)->texture->setWrap(osg::Texture::WRAP_R,osg::Texture::REPEAT);*/
653  OSGL(ifp)->pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, OSGL(ifp)->texture, osg::StateAttribute::ON);
654 
655  if (have_pixbuff) {
656  OSGL(ifp)->use_texture = 1;
657  osg::Geode *geode = new osg::Geode;
658  osg::StateSet* stateset = geode->getOrCreateStateSet();
659  stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
660  geode->addDrawable(OSGL(ifp)->pictureQuad);
661  OSGL(ifp)->root->addChild(geode);
662  osg::Vec3 topleft(0.0f, 0.0f, 0.0f);
663  osg::Vec3 bottomright(ifp->if_width, ifp->if_height, 0.0f);
664  camera->setProjectionMatrixAsOrtho2D(-ifp->if_width/2,ifp->if_width/2,-ifp->if_height/2, ifp->if_height/2);
665  } else {
666  /* Emulate xmit_scanlines drawing in OSG as a fallback... */
667  OSGL(ifp)->use_texture = 0;
668  osg::Vec3 topleft(0.0f, 0.0f, 0.0f);
669  osg::Vec3 bottomright(ifp->if_width, ifp->if_height, 0.0f);
670  camera->setProjectionMatrixAsOrtho2D(-ifp->if_width/2,ifp->if_width/2,-ifp->if_height/2, ifp->if_height/2);
671  }
672 
673  OSGL(ifp)->viewer->setCameraManipulator( new osgGA::FrameBufferManipulator() );
674  OSGL(ifp)->viewer->addEventHandler(new osgGA::StateSetManipulator(OSGL(ifp)->viewer->getCamera()->getOrCreateStateSet()));
675 
676  KeyHandler *kh = new KeyHandler(*(OSGL(ifp)->root));
677  kh->fbp = ifp;
678  OSGL(ifp)->viewer->addEventHandler(kh);
679 
680  OSGL(ifp)->cursor_on = 1;
681 
682 
683  OSGL(ifp)->timer->setStartTick();
684  /* count windows */
685  osgl_nwindows++;
686 
687  OSGL(ifp)->alive = 1;
688  OSGL(ifp)->firstTime = 1;
689 
690  return 0;
691 
692 }
693 
694 
695 
696 int
697 _osgl_open_existing(fb *ifp, int width, int height, void *glc, void *traits)
698 {
699 
700  /*XXX for now use private memory */
701  ifp->if_mode = MODE_1MALLOC;
702 
703  /*
704  * Allocate extension memory sections,
705  * addressed by SGI(ifp)->mi_xxx and OSGL(ifp)->xxx
706  */
707 
708  if ((SGIL(ifp) = (char *)calloc(1, sizeof(struct sgiinfo))) == NULL) {
709  fb_log("fb_osgl_open: sgiinfo malloc failed\n");
710  return -1;
711  }
712  if ((OSGLL(ifp) = (char *)calloc(1, sizeof(struct osglinfo))) == NULL) {
713  fb_log("fb_osgl_open: osglinfo malloc failed\n");
714  return -1;
715  }
716 
717  OSGL(ifp)->use_ext_ctrl = 1;
718 
719  SGI(ifp)->mi_shmid = -1; /* indicate no shared memory */
720  ifp->if_width = ifp->if_max_width = width;
721  ifp->if_height = ifp->if_max_height = height;
722 
723  OSGL(ifp)->win_width = OSGL(ifp)->vp_width = width;
724  OSGL(ifp)->win_height = OSGL(ifp)->vp_height = height;
725 
726  OSGL(ifp)->cursor_on = 1;
727 
728  /* initialize window state variables before calling osgl_getmem */
729  ifp->if_zoomflag = 0;
730  ifp->if_xzoom = 1; /* for zoom fakeout */
731  ifp->if_yzoom = 1; /* for zoom fakeout */
732  ifp->if_xcenter = width/2;
733  ifp->if_ycenter = height/2;
734  SGI(ifp)->mi_pid = bu_process_id();
735 
736  /* Attach to shared memory, potentially with a screen repaint */
737  if (osgl_getmem(ifp) < 0)
738  return -1;
739 
740  OSGL(ifp)->viewer = NULL;
741  OSGL(ifp)->glc = (osg::GraphicsContext *)glc;
742  OSGL(ifp)->traits = (osg::GraphicsContext::Traits *)traits;
743 
744  ++osgl_nwindows;
745 
746  OSGL(ifp)->alive = 1;
747  OSGL(ifp)->firstTime = 1;
748 
749  osgl_clipper(ifp);
750 
751  return 0;
752 }
753 
755 osgl_get_fbps(uint32_t magic)
756 {
757  struct fb_platform_specific *fb_ps = NULL;
758  struct osgl_fb_info *data = NULL;
759  BU_GET(fb_ps, struct fb_platform_specific);
760  BU_GET(data, struct osgl_fb_info);
761  fb_ps->magic = magic;
762  fb_ps->data = data;
763  return fb_ps;
764 }
765 
766 
767 HIDDEN void
768 osgl_put_fbps(struct fb_platform_specific *fbps)
769 {
770  BU_CKMAG(fbps, FB_OSGL_MAGIC, "osgl framebuffer");
771  BU_PUT(fbps->data, struct osgl_fb_info);
772  BU_PUT(fbps, struct fb_platform_specific);
773  return;
774 }
775 
776 HIDDEN int
777 osgl_open_existing(fb *ifp, int width, int height, struct fb_platform_specific *fb_p)
778 {
779  struct osgl_fb_info *osgl_internal = (struct osgl_fb_info *)fb_p->data;
780  BU_CKMAG(fb_p, FB_OSGL_MAGIC, "osgl framebuffer");
781  return _osgl_open_existing(ifp, width, height, osgl_internal->glc, osgl_internal->traits);
782 }
783 
784 
785 HIDDEN int
786 osgl_final_close(fb *ifp)
787 {
788 
789  if (CJDEBUG) {
790  printf("osgl_final_close: All done...goodbye!\n");
791  }
792 
793  if (OSGL(ifp)->viewer) {
794  OSGL(ifp)->viewer->setDone(true);
795  } else {
796  if (OSGL(ifp)->glc) {
797  OSGL(ifp)->glc->makeCurrent();
798  OSGL(ifp)->glc->releaseContext();
799  }
800  }
801 
802  if (SGIL(ifp) != NULL) {
803  /* free up memory associated with image */
804 #ifdef HAVE_SYS_SHM_H
805  if (SGI(ifp)->mi_shmid != -1) {
806  /* detach from shared memory */
807  if (shmdt(ifp->if_mem) == -1) {
808  fb_log("fb_osgl_close shmdt failed, errno=%d\n",
809  errno);
810  return -1;
811  }
812  } else {
813 #endif
814  /* free private memory */
815  (void)free(ifp->if_mem);
816 #ifdef HAVE_SYS_SHM_H
817  }
818 #endif
819  /* free state information */
820  (void)free((char *)SGIL(ifp));
821  SGIL(ifp) = NULL;
822  }
823 
824  if (OSGLL(ifp) != NULL) {
825  (void)free((char *)OSGLL(ifp));
826  OSGLL(ifp) = NULL;
827  }
828 
829  osgl_nwindows--;
830  return 0;
831 }
832 
833 
834 HIDDEN int
835 osgl_flush(fb *UNUSED(ifp))
836 {
837  glFlush();
838  return 0;
839 }
840 
841 
842 HIDDEN int
843 fb_osgl_close(fb *ifp)
844 {
845  osgl_flush(ifp);
846 
847  /* only the last open window can linger -
848  * call final_close if not lingering
849  */
850  if (osgl_nwindows > 1 ||
851  (ifp->if_mode & MODE_2MASK) == MODE_2TRANSIENT)
852  return osgl_final_close(ifp);
853 
854  if (CJDEBUG)
855  printf("fb_osgl_close: remaining open to linger awhile.\n");
856 
857  /*
858  * else:
859  *
860  * LINGER mode. Don't return to caller until user mouses "close"
861  * menu item. This may delay final processing in the calling
862  * function for some time, but the assumption is that the user
863  * wishes to compare this image with others.
864  *
865  * Since we plan to linger here, long after our invoker expected
866  * us to be gone, be certain that no file descriptors remain open
867  * to associate us with pipelines, network connections, etc., that
868  * were ALREADY ESTABLISHED before the point that fb_open() was
869  * called.
870  *
871  * The simple for i=0..20 loop will not work, because that smashes
872  * some window-manager files. Therefore, we content ourselves
873  * with eliminating stdin, in the hopes that this will
874  * successfully terminate any pipes or network connections.
875  * Standard error/out may be used to print framebuffer debug
876  * messages, so they're kept around.
877  */
878  fclose(stdin);
879 
880  if (OSGL(ifp)->viewer) {
881  return (*OSGL(ifp)->viewer).ViewerBase::run();
882  } else {
883  /* Shouldn't get here - lingering windows should be using the viewer,
884  * and embedded ones should use osgl_close_existing */
885  return 0;
886  }
887 }
888 
889 
890 int
891 osgl_close_existing(fb *ifp)
892 {
893  if (SGIL(ifp) != NULL) {
894 #ifdef HAVE_SYS_SHM_H
895  /* free up memory associated with image */
896  if (SGI(ifp)->mi_shmid != -1) {
897  /* detach from shared memory */
898  if (shmdt(ifp->if_mem) == -1) {
899  fb_log("fb_osgl_close: shmdt failed, errno=%d\n",
900  errno);
901  return -1;
902  }
903  } else {
904 #endif
905  /* free private memory */
906  (void)free(ifp->if_mem);
907 #ifdef HAVE_SYS_SHM_H
908  }
909 #endif
910  /* free state information */
911  (void)free((char *)SGIL(ifp));
912  SGIL(ifp) = NULL;
913  }
914 
915  if (OSGLL(ifp) != NULL) {
916  (void)free((char *)OSGLL(ifp));
917  OSGLL(ifp) = NULL;
918  }
919 
920  return 0;
921 }
922 
923 
924 /*
925  * Handle any pending input events
926  */
927 HIDDEN int
928 osgl_poll(fb *ifp)
929 {
930  osgl_do_event(ifp);
931 
932  if (OSGL(ifp)->alive < 0)
933  return 1;
934  else
935  return 0;
936 }
937 
938 
939 /*
940  * Free shared memory resources, and close.
941  */
942 HIDDEN int
943 osgl_free(fb *ifp)
944 {
945  int ret;
946 
947  if (CJDEBUG) printf("entering osgl_free\n");
948  /* Close the framebuffer */
949  ret = osgl_final_close(ifp);
950 
951  if ((ifp->if_mode & MODE_1MASK) == MODE_1SHARED) {
952  /* If shared mem, release the shared memory segment */
953  osgl_zapmem();
954  }
955  return ret;
956 }
957 
958 
959 HIDDEN int
960 osgl_clear(fb *ifp, unsigned char *pp)
961 {
962  struct osgl_pixel bg;
963  register struct osgl_pixel *osglp;
964  register int cnt;
965  register int y;
966 
967  if (CJDEBUG) printf("entering osgl_clear\n");
968 
969  /* Set clear colors */
970  if (pp != RGBPIXEL_NULL) {
971  bg.alpha = 0;
972  bg.red = (pp)[RED];
973  bg.green = (pp)[GRN];
974  bg.blue = (pp)[BLU];
975  } else {
976  bg.alpha = 0;
977  bg.red = 0;
978  bg.green = 0;
979  bg.blue = 0;
980  }
981 
982  /* Flood rectangle in shared memory */
983  for (y = 0; y < ifp->if_height; y++) {
984  if (!OSGL(ifp)->viewer) {
985  osglp = (struct osgl_pixel *)&ifp->if_mem[(y*SGI(ifp)->mi_memwidth+0)*sizeof(struct osgl_pixel) ];
986  } else {
987  osglp = (struct osgl_pixel *)(OSGL(ifp)->image->data(0,y,0));
988  }
989  for (cnt = ifp->if_width-1; cnt >= 0; cnt--) {
990  *osglp++ = bg; /* struct copy */
991  }
992  }
993 
994  if (OSGL(ifp)->use_ext_ctrl) {
995  return 0;
996  }
997 
998  if (OSGL(ifp)->viewer) {
999  OSGL(ifp)->image->dirty();
1000  if (OSGL(ifp)->timer->time_m() - OSGL(ifp)->last_update_time > 10) {
1001  OSGL(ifp)->viewer->frame();
1002  OSGL(ifp)->last_update_time = OSGL(ifp)->timer->time_m();
1003  }
1004  } else {
1005  OSGL(ifp)->glc->makeCurrent();
1006 
1007  if (pp != RGBPIXEL_NULL) {
1008  glClearColor(pp[RED]/255.0, pp[GRN]/255.0, pp[BLU]/255.0, 0.0);
1009  } else {
1010  glClearColor(0, 0, 0, 0);
1011  }
1012 
1013  glClear(GL_COLOR_BUFFER_BIT);
1014  OSGL(ifp)->glc->swapBuffers();
1015 
1016  /* unattach context for other threads to use */
1017  OSGL(ifp)->glc->releaseContext();
1018  }
1019 
1020  return 0;
1021 }
1022 
1023 
1024 HIDDEN int
1025 osgl_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
1026 {
1027  struct osgl_clip *clp;
1028 
1029  if (CJDEBUG) printf("entering osgl_view\n");
1030 
1031  if (xzoom < 1) xzoom = 1;
1032  if (yzoom < 1) yzoom = 1;
1033  if (ifp->if_xcenter == xcenter && ifp->if_ycenter == ycenter
1034  && ifp->if_xzoom == xzoom && ifp->if_yzoom == yzoom)
1035  return 0;
1036 
1037  if (xcenter < 0 || xcenter >= ifp->if_width)
1038  return -1;
1039  if (ycenter < 0 || ycenter >= ifp->if_height)
1040  return -1;
1041  if (xzoom >= ifp->if_width || yzoom >= ifp->if_height)
1042  return -1;
1043 
1044  ifp->if_xcenter = xcenter;
1045  ifp->if_ycenter = ycenter;
1046  ifp->if_xzoom = xzoom;
1047  ifp->if_yzoom = yzoom;
1048 
1049  if (ifp->if_xzoom > 1 || ifp->if_yzoom > 1)
1050  ifp->if_zoomflag = 1;
1051  else ifp->if_zoomflag = 0;
1052 
1053 
1054  if (OSGL(ifp)->use_ext_ctrl) {
1055  osgl_clipper(ifp);
1056  } else {
1057 
1058  if (!OSGL(ifp)->viewer && OSGL(ifp)->glc) {
1059  OSGL(ifp)->glc->makeCurrent();
1060 
1061  /* Set clipping matrix and zoom level */
1062  glMatrixMode(GL_PROJECTION);
1063  glLoadIdentity();
1064 
1065  osgl_clipper(ifp);
1066  clp = &(OSGL(ifp)->clip);
1067  glOrtho(clp->oleft, clp->oright, clp->obottom, clp->otop, -1.0, 1.0);
1068  glPixelZoom((float) ifp->if_xzoom, (float) ifp->if_yzoom);
1069 
1070  osgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1071  OSGL(ifp)->glc->swapBuffers();
1072  glFlush();
1073 
1074  /* unattach context for other threads to use */
1075  OSGL(ifp)->glc->releaseContext();
1076  }
1077  }
1078 
1079  return 0;
1080 }
1081 
1082 
1083 HIDDEN int
1084 osgl_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
1085 {
1086  if (CJDEBUG) printf("entering osgl_getview\n");
1087 
1088  *xcenter = ifp->if_xcenter;
1089  *ycenter = ifp->if_ycenter;
1090  *xzoom = ifp->if_xzoom;
1091  *yzoom = ifp->if_yzoom;
1092 
1093  return 0;
1094 }
1095 
1096 
1097 /* read count pixels into pixelp starting at x, y */
1099 osgl_read(fb *ifp, int x, int y, unsigned char *pixelp, size_t count)
1100 {
1101  size_t n;
1102  size_t scan_count; /* # pix on this scanline */
1103  register unsigned char *cp;
1104  ssize_t ret;
1105  register struct osgl_pixel *osglp;
1106 
1107  if (CJDEBUG) printf("entering osgl_read\n");
1108 
1109  if (x < 0 || x >= ifp->if_width ||
1110  y < 0 || y >= ifp->if_height)
1111  return -1;
1112 
1113  ret = 0;
1114  cp = (unsigned char *)(pixelp);
1115 
1116  while (count) {
1117  if (y >= ifp->if_height)
1118  break;
1119 
1120  if (count >= (size_t)(ifp->if_width-x))
1121  scan_count = ifp->if_width-x;
1122  else
1123  scan_count = count;
1124 
1125  if (!OSGL(ifp)->viewer) {
1126  osglp = (struct osgl_pixel *)&ifp->if_mem[(y*SGI(ifp)->mi_memwidth+x)*sizeof(struct osgl_pixel) ];
1127  } else {
1128  osglp = (struct osgl_pixel *)(OSGL(ifp)->image->data(0,y,0));
1129  }
1130 
1131  n = scan_count;
1132  while (n) {
1133  cp[RED] = osglp->red;
1134  cp[GRN] = osglp->green;
1135  cp[BLU] = osglp->blue;
1136  osglp++;
1137  cp += 3;
1138  n--;
1139  }
1140  ret += scan_count;
1141  count -= scan_count;
1142  x = 0;
1143  /* Advance upwards */
1144  if (++y >= ifp->if_height)
1145  break;
1146  }
1147  return ret;
1148 }
1149 
1150 
1151 /* write count pixels from pixelp starting at xstart, ystart */
1153 osgl_write(fb *ifp, int xstart, int ystart, const unsigned char *pixelp, size_t count)
1154 {
1155  register int x;
1156  register int y;
1157  size_t scan_count; /* # pix on this scanline */
1158  size_t pix_count; /* # pixels to send */
1159  ssize_t ret;
1160 
1161  FB_CK_FB(ifp);
1162 
1163  if (CJDEBUG) printf("entering osgl_write\n");
1164 
1165  /* fast exit cases */
1166  pix_count = count;
1167  if (pix_count == 0)
1168  return 0; /* OK, no pixels transferred */
1169 
1170  x = xstart;
1171  y = ystart;
1172 
1173  if (x < 0 || x >= ifp->if_width ||
1174  y < 0 || y >= ifp->if_height)
1175  return -1;
1176 
1177  ret = 0;
1178 
1179  if (OSGL(ifp)->viewer) {
1180 
1181  while (pix_count) {
1182  void *scanline;
1183 
1184  if (y >= ifp->if_height)
1185  break;
1186 
1187  if (pix_count >= (size_t)(ifp->if_width-x))
1188  scan_count = (size_t)(ifp->if_width-x);
1189  else
1190  scan_count = pix_count;
1191 
1192  if (OSGL(ifp)->use_texture) {
1193  scanline = (void *)(OSGL(ifp)->image->data(0,y,0));
1194  memcpy(scanline, pixelp, scan_count*3);
1195  } else {
1196  /* Emulate xmit_scanlines drawing in OSG as a fallback when textures don't work... */
1197  osg::ref_ptr<osg::Image> scanline_image = new osg::Image;
1198  scanline_image->allocateImage(ifp->if_width, 1, 1, GL_RGB, GL_UNSIGNED_BYTE);
1199  scanline = (void *)scanline_image->data();
1200  memcpy(scanline, pixelp, scan_count*3);
1201  osg::ref_ptr<osg::DrawPixels> scanline_obj = new osg::DrawPixels;
1202  scanline_obj->setPosition(osg::Vec3(-ifp->if_width/2, 0, -ifp->if_height/2 + y));
1203  scanline_obj->setImage(scanline_image);
1204  osg::ref_ptr<osg::Geode> new_geode = new osg::Geode;
1205  osg::StateSet* stateset = new_geode->getOrCreateStateSet();
1206  stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
1207  new_geode->addDrawable(scanline_obj.get());
1208  OSGL(ifp)->root->addChild(new_geode.get());
1209  }
1210  ret += scan_count;
1211  pix_count -= scan_count;
1212  x = 0;
1213  if (++y >= ifp->if_height)
1214  break;
1215  }
1216 
1217  OSGL(ifp)->image->dirty();
1218  if (OSGL(ifp)->timer->time_m() - OSGL(ifp)->last_update_time > 10) {
1219  OSGL(ifp)->viewer->frame();
1220  OSGL(ifp)->last_update_time = OSGL(ifp)->timer->time_m();
1221  }
1222 
1223  return ret;
1224 
1225  } else {
1226 
1227  register unsigned char *cp;
1228  int ybase;
1229 
1230  ybase = ystart;
1231  cp = (unsigned char *)(pixelp);
1232 
1233  while (pix_count) {
1234  size_t n;
1235  register struct osgl_pixel *osglp;
1236 
1237  if (y >= ifp->if_height)
1238  break;
1239 
1240  if (pix_count >= (size_t)(ifp->if_width-x))
1241  scan_count = (size_t)(ifp->if_width-x);
1242  else
1243  scan_count = pix_count;
1244 
1245  if (!OSGL(ifp)->viewer) {
1246  osglp = (struct osgl_pixel *)&ifp->if_mem[(y*SGI(ifp)->mi_memwidth+x)*sizeof(struct osgl_pixel) ];
1247  } else {
1248  osglp = (struct osgl_pixel *)(OSGL(ifp)->image->data(0,y,0));
1249  }
1250 
1251  n = scan_count;
1252  if ((n & 3) != 0) {
1253  /* This code uses 60% of all CPU time */
1254  while (n) {
1255  /* alpha channel is always zero */
1256  osglp->red = cp[RED];
1257  osglp->green = cp[GRN];
1258  osglp->blue = cp[BLU];
1259  osglp++;
1260  cp += 3;
1261  n--;
1262  }
1263  } else {
1264  while (n) {
1265  /* alpha channel is always zero */
1266  osglp[0].red = cp[RED+0*3];
1267  osglp[0].green = cp[GRN+0*3];
1268  osglp[0].blue = cp[BLU+0*3];
1269  osglp[1].red = cp[RED+1*3];
1270  osglp[1].green = cp[GRN+1*3];
1271  osglp[1].blue = cp[BLU+1*3];
1272  osglp[2].red = cp[RED+2*3];
1273  osglp[2].green = cp[GRN+2*3];
1274  osglp[2].blue = cp[BLU+2*3];
1275  osglp[3].red = cp[RED+3*3];
1276  osglp[3].green = cp[GRN+3*3];
1277  osglp[3].blue = cp[BLU+3*3];
1278  osglp += 4;
1279  cp += 3*4;
1280  n -= 4;
1281  }
1282  }
1283  ret += scan_count;
1284  pix_count -= scan_count;
1285  x = 0;
1286  if (++y >= ifp->if_height)
1287  break;
1288  }
1289 
1290  if (!OSGL(ifp)->use_ext_ctrl) {
1291  OSGL(ifp)->glc->makeCurrent();
1292  if (xstart + count < (size_t)ifp->if_width) {
1293  osgl_xmit_scanlines(ifp, ybase, 1, xstart, count);
1294  } else {
1295  /* Normal case -- multi-pixel write */
1296  osgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1297  }
1298  OSGL(ifp)->glc->swapBuffers();
1299  glFlush();
1300  /* unattach context for other threads to use */
1301  OSGL(ifp)->glc->releaseContext();
1302  }
1303 
1304  return ret;
1305 
1306  }
1307 
1308  return 0;
1309 }
1310 
1311 
1312 /*
1313  * The task of this routine is to reformat the pixels into SGI
1314  * internal form, and then arrange to have them sent to the screen
1315  * separately.
1316  */
1317 HIDDEN int
1318 osgl_writerect(fb *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp)
1319 {
1320  register int x;
1321  register int y;
1322  register unsigned char *cp;
1323  register struct osgl_pixel *osglp;
1324 
1325  if (CJDEBUG) printf("entering osgl_writerect\n");
1326 
1327  if (width <= 0 || height <= 0)
1328  return 0; /* do nothing */
1329  if (xmin < 0 || xmin+width > ifp->if_width ||
1330  ymin < 0 || ymin+height > ifp->if_height)
1331  return -1; /* no can do */
1332 
1333  cp = (unsigned char *)(pp);
1334  for (y = ymin; y < ymin+height; y++) {
1335  if (!OSGL(ifp)->viewer) {
1336  osglp = (struct osgl_pixel *)&ifp->if_mem[(y*SGI(ifp)->mi_memwidth+xmin)*sizeof(struct osgl_pixel) ];
1337  } else {
1338  osglp = (struct osgl_pixel *)(OSGL(ifp)->image->data(0,y,0));
1339  }
1340  for (x = xmin; x < xmin+width; x++) {
1341  /* alpha channel is always zero */
1342  osglp->red = cp[RED];
1343  osglp->green = cp[GRN];
1344  osglp->blue = cp[BLU];
1345  osglp++;
1346  cp += 3;
1347  }
1348  }
1349 
1350  if (!OSGL(ifp)->use_ext_ctrl) {
1351  if (OSGL(ifp)->viewer) {
1352  OSGL(ifp)->image->dirty();
1353  if (OSGL(ifp)->timer->time_m() - OSGL(ifp)->last_update_time > 10) {
1354  OSGL(ifp)->viewer->frame();
1355  OSGL(ifp)->last_update_time = OSGL(ifp)->timer->time_m();
1356  }
1357  } else {
1358  OSGL(ifp)->glc->makeCurrent();
1359  osgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1360  OSGL(ifp)->glc->swapBuffers();
1361  /* unattach context for other threads to use */
1362  OSGL(ifp)->glc->releaseContext();
1363  }
1364  }
1365 
1366  return width*height;
1367 }
1368 
1369 
1370 /*
1371  * The task of this routine is to reformat the pixels into SGI
1372  * internal form, and then arrange to have them sent to the screen
1373  * separately.
1374  */
1375 HIDDEN int
1376 osgl_bwwriterect(fb *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp)
1377 {
1378  register int x;
1379  register int y;
1380  register unsigned char *cp;
1381  register struct osgl_pixel *osglp;
1382 
1383  if (CJDEBUG) printf("entering osgl_bwwriterect\n");
1384 
1385  if (width <= 0 || height <= 0)
1386  return 0; /* do nothing */
1387  if (xmin < 0 || xmin+width > ifp->if_width ||
1388  ymin < 0 || ymin+height > ifp->if_height)
1389  return -1; /* no can do */
1390 
1391  cp = (unsigned char *)(pp);
1392  for (y = ymin; y < ymin+height; y++) {
1393  if (!OSGL(ifp)->viewer) {
1394  osglp = (struct osgl_pixel *)&ifp->if_mem[(y*SGI(ifp)->mi_memwidth+xmin)*sizeof(struct osgl_pixel) ];
1395  } else {
1396  osglp = (struct osgl_pixel *)(OSGL(ifp)->image->data(0,y,0));
1397  }
1398  for (x = xmin; x < xmin+width; x++) {
1399  register int val;
1400  /* alpha channel is always zero */
1401  osglp->red = (val = *cp++);
1402  osglp->green = val;
1403  osglp->blue = val;
1404  osglp++;
1405  }
1406  }
1407 
1408  if (!OSGL(ifp)->use_ext_ctrl) {
1409  if (OSGL(ifp)->viewer) {
1410  OSGL(ifp)->image->dirty();
1411  if (OSGL(ifp)->timer->time_m() - OSGL(ifp)->last_update_time > 10) {
1412  OSGL(ifp)->viewer->frame();
1413  OSGL(ifp)->last_update_time = OSGL(ifp)->timer->time_m();
1414  }
1415  } else {
1416  OSGL(ifp)->glc->makeCurrent();
1417  osgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1418  OSGL(ifp)->glc->swapBuffers();
1419  /* unattach context for other threads to use */
1420  OSGL(ifp)->glc->releaseContext();
1421  }
1422  }
1423 
1424  return width*height;
1425 }
1426 
1427 
1428 HIDDEN int
1429 osgl_rmap(register fb *ifp, register ColorMap *cmp)
1430 {
1431  register int i;
1432 
1433  if (CJDEBUG) printf("entering osgl_rmap\n");
1434 
1435  /* Just parrot back the stored colormap */
1436  for (i = 0; i < 256; i++) {
1437  cmp->cm_red[i] = CMR(ifp)[i]<<8;
1438  cmp->cm_green[i] = CMG(ifp)[i]<<8;
1439  cmp->cm_blue[i] = CMB(ifp)[i]<<8;
1440  }
1441  return 0;
1442 }
1443 
1444 
1445 HIDDEN int
1446 osgl_wmap(register fb *ifp, register const ColorMap *cmp)
1447 {
1448  register int i;
1449  int prev; /* !0 = previous cmap was non-linear */
1450 
1451  if (CJDEBUG) printf("entering osgl_wmap\n");
1452 
1453  prev = SGI(ifp)->mi_cmap_flag;
1454  if (cmp == COLORMAP_NULL) {
1455  osgl_cminit(ifp);
1456  } else {
1457  for (i = 0; i < 256; i++) {
1458  CMR(ifp)[i] = cmp-> cm_red[i]>>8;
1459  CMG(ifp)[i] = cmp-> cm_green[i]>>8;
1460  CMB(ifp)[i] = cmp-> cm_blue[i]>>8;
1461  }
1462  }
1463  SGI(ifp)->mi_cmap_flag = !is_linear_cmap(ifp);
1464 
1465 
1466  if (!OSGL(ifp)->use_ext_ctrl) {
1467  /* if current and previous maps are linear, return */
1468  if (SGI(ifp)->mi_cmap_flag == 0 && prev == 0) return 0;
1469 
1470  /* Software color mapping, trigger a repaint */
1471  if (OSGL(ifp)->viewer) {
1472  OSGL(ifp)->image->dirty();
1473  if (OSGL(ifp)->timer->time_m() - OSGL(ifp)->last_update_time > 10) {
1474  OSGL(ifp)->viewer->frame();
1475  OSGL(ifp)->last_update_time = OSGL(ifp)->timer->time_m();
1476  }
1477  } else {
1478  OSGL(ifp)->glc->makeCurrent();
1479  osgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1480  OSGL(ifp)->glc->swapBuffers();
1481  /* unattach context for other threads to use, also flushes */
1482  OSGL(ifp)->glc->releaseContext();
1483  }
1484  }
1485 
1486  return 0;
1487 }
1488 
1489 
1490 HIDDEN int
1491 osgl_help(fb *ifp)
1492 {
1493  fb_log("Description: %s\n", ifp->if_type);
1494  fb_log("Device: %s\n", ifp->if_name);
1495  fb_log("Max width height: %d %d\n",
1496  ifp->if_max_width,
1497  ifp->if_max_height);
1498  fb_log("Default width height: %d %d\n",
1499  ifp->if_width,
1500  ifp->if_height);
1501  fb_log("Usage: /dev/osgl\n");
1502 
1503  fb_log("\nCurrent internal state:\n");
1504  fb_log(" mi_cmap_flag=%d\n", SGI(ifp)->mi_cmap_flag);
1505  fb_log(" osgl_nwindows=%d\n", osgl_nwindows);
1506  return 0;
1507 }
1508 
1509 
1510 HIDDEN int
1511 osgl_setcursor(fb *ifp, const unsigned char *UNUSED(bits), int UNUSED(xbits), int UNUSED(ybits), int UNUSED(xorig), int UNUSED(yorig))
1512 {
1513  FB_CK_FB(ifp);
1514 
1515  // If it should ever prove desirable to alter the cursor or disable it, here's how it is done:
1516  // dynamic_cast<osgViewer::GraphicsWindow*>(camera->getGraphicsContext()))->setCursor(osgViewer::GraphicsWindow::NoCursor);
1517 
1518  return 0;
1519 }
1520 
1521 
1522 HIDDEN int
1523 osgl_cursor(fb *UNUSED(ifp), int UNUSED(mode), int UNUSED(x), int UNUSED(y))
1524 {
1525 
1526  fb_log("osgl_cursor\n");
1527  return 0;
1528 }
1529 
1530 
1531 int
1532 osgl_refresh(fb *ifp, int x, int y, int w, int h)
1533 {
1534  int mm;
1535  struct osgl_clip *clp;
1536 
1537  if (w < 0) {
1538  w = -w;
1539  x -= w;
1540  }
1541 
1542  if (h < 0) {
1543  h = -h;
1544  y -= h;
1545  }
1546 
1547  glGetIntegerv(GL_MATRIX_MODE, &mm);
1548  glMatrixMode(GL_PROJECTION);
1549  glPushMatrix();
1550  glLoadIdentity();
1551 
1552  osgl_clipper(ifp);
1553  clp = &(OSGL(ifp)->clip);
1554  glOrtho(clp->oleft, clp->oright, clp->obottom, clp->otop, -1.0, 1.0);
1555  glPixelZoom((float) ifp->if_xzoom, (float) ifp->if_yzoom);
1556 
1557  glMatrixMode(GL_MODELVIEW);
1558  glPushMatrix();
1559  glLoadIdentity();
1560 
1561  glViewport(0, 0, OSGL(ifp)->win_width, OSGL(ifp)->win_height);
1562  osgl_xmit_scanlines(ifp, y, h, x, w);
1563  glMatrixMode(GL_PROJECTION);
1564  glPopMatrix();
1565  glMatrixMode(GL_MODELVIEW);
1566  glPopMatrix();
1567  glMatrixMode(mm);
1568 
1569  if (!OSGL(ifp)->use_ext_ctrl) {
1570  glFlush();
1571  }
1572 
1573  return 0;
1574 }
1575 
1576 
1577 /* This is the ONLY thing that we normally "export" */
1578 fb osgl_interface =
1579 {
1580  0, /* magic number slot */
1581  FB_OSGL_MAGIC,
1582  fb_osgl_open, /* open device */
1583  osgl_open_existing, /* existing device_open */
1584  osgl_close_existing, /* existing device_close */
1585  osgl_get_fbps, /* get platform specific memory */
1586  osgl_put_fbps, /* free platform specific memory */
1587  fb_osgl_close, /* close device */
1588  osgl_clear, /* clear device */
1589  osgl_read, /* read pixels */
1590  osgl_write, /* write pixels */
1591  osgl_rmap, /* read colormap */
1592  osgl_wmap, /* write colormap */
1593  osgl_view, /* set view */
1594  osgl_getview, /* get view */
1595  osgl_setcursor, /* define cursor */
1596  osgl_cursor, /* set cursor */
1597  fb_sim_getcursor, /* get cursor */
1598  fb_sim_readrect, /* read rectangle */
1599  osgl_writerect, /* write rectangle */
1601  osgl_bwwriterect, /* write rectangle */
1602  osgl_configureWindow,
1603  osgl_refresh,
1604  osgl_poll, /* process events */
1605  osgl_flush, /* flush output */
1606  osgl_free, /* free resources */
1607  osgl_help, /* help message */
1608  bu_strdup("OpenSceneGraph OpenGL"), /* device description */
1609  XMAXSCREEN+1, /* max width */
1610  YMAXSCREEN+1, /* max height */
1611  bu_strdup("/dev/osgl"), /* short device name */
1612  512, /* default/current width */
1613  512, /* default/current height */
1614  -1, /* select file desc */
1615  -1, /* file descriptor */
1616  1, 1, /* zoom */
1617  256, 256, /* window center */
1618  0, 0, 0, /* cursor */
1619  PIXEL_NULL, /* page_base */
1620  PIXEL_NULL, /* page_curp */
1621  PIXEL_NULL, /* page_endp */
1622  -1, /* page_no */
1623  0, /* page_dirty */
1624  0L, /* page_curpos */
1625  0L, /* page_pixels */
1626  0, /* debug */
1627  50000, /* refresh rate */
1628  {0}, /* u1 */
1629  {0}, /* u2 */
1630  {0}, /* u3 */
1631  {0}, /* u4 */
1632  {0}, /* u5 */
1633  {0} /* u6 */
1634 };
1635 
1636 /* Because class is actually used to access a struct
1637  * entry in this file, preserve our redefinition
1638  * of class for the benefit of avoiding C++ name
1639  * collisions until the end of this file */
1640 #undef class
1641 
1642 #else
1643 
1644 /* quell empty-compilation unit warnings */
1645 static const int unused = 0;
1646 
1647 #endif /* IF_OSGL */
1648 
1649 /*
1650  * Local Variables:
1651  * mode: C
1652  * tab-width: 8
1653  * indent-tabs-mode: t
1654  * c-file-style: "stroustrup"
1655  * End:
1656  * ex: shiftwidth=4 tabstop=8
1657  */
Definition: db_flip.c:35
ptrdiff_t ssize_t
Definition: common.h:119
#define COLORMAP_NULL
Definition: fb.h:91
#define SHMEM_KEY
Definition: fb_private.h:65
void fb_log(const char *fmt,...) _BU_ATTR_PRINTF12
Definition: fb_log.c:42
void * data
Definition: fb.h:176
unsigned short cm_green[256]
Definition: fb.h:84
#define BU_CKMAG(_ptr, _magic, _str)
Definition: magic.h:233
#define MODE_1MASK
Definition: if_mem.c:55
#define RED
Definition: color.h:39
#define PIXEL_NULL
Definition: fb.h:89
int bu_process_id(void)
Definition: process.c:31
int if_xzoom
zoom factors
Definition: fb_private.h:120
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 if_max_width
max device width
Definition: fb_private.h:111
#define BLU
Definition: color.h:41
ustring width
#define HIDDEN
Definition: common.h:86
char * if_type
what "open" calls it
Definition: fb_private.h:110
int if_ycenter
Definition: fb_private.h:123
if(share_geom)
Definition: nmg_mod.c:3829
COMPLEX data[64]
Definition: fftest.c:34
#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
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
unsigned short cm_red[256]
Definition: fb.h:83
int if_max_height
max device height
Definition: fb_private.h:112
oldeumate l2 magic
Definition: nmg_mod.c:3843
ustring camera
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
union fb_internal::@15 u6
#define RGBPIXEL_NULL
Definition: fb.h:90
ustring alpha
Definition: fb.h:82
const char * bu_brlcad_dir(const char *dirkey, int fail_quietly)
Definition: brlcad_path.c:231
uint32_t magic
Definition: fb.h:176
int clip(fastf_t *, fastf_t *, fastf_t *, fastf_t *)
Definition: clip.c:66
int bu_shmget(int *shmid, char **shared_memory, int key, size_t size)
Definition: malloc.c:692
char * p
Definition: fb_private.h:138
#define MODE_2MASK
Definition: if_mem.c:59
A frame-buffer IO structure.
Definition: fb_private.h:80
int if_width
current values
Definition: fb_private.h:115
const char * bu_brlcad_root(const char *rhs, int fail_quietly)
Definition: brlcad_path.c:292
unsigned short cm_blue[256]
Definition: fb.h:85
#define GRN
Definition: color.h:40
#define FB_OSGL_MAGIC
Definition: magic.h:192
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
#define bu_strdup(s)
Definition: str.h:71
int if_xcenter
pan position
Definition: fb_private.h:122