BRL-CAD
if_wgl.c
Go to the documentation of this file.
1 /* I F _ W G L . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-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_wgl.c
23  *
24  * Frame Buffer Library interface for Windows OpenGL.
25  *
26  * There are several different Frame Buffer modes supported. Set your
27  * environment FB_FILE to the appropriate type. Note that some of the
28  * /dev/sgi modes are not supported, and there are some new
29  * modes. (see the modeflag definitions below).
30  *
31  * /dev/wgl[options]
32  *
33  */
34 /** @} */
35 
36 #include "common.h"
37 
38 #ifdef IF_WGL
39 
40 #include <stdlib.h>
41 #include <ctype.h>
42 #include <errno.h>
43 
44 /* winsock (bsocket.h) first, ordering matters */
45 #include "bsocket.h"
46 #include "bio.h"
47 #include <windowsx.h>
48 
49 #ifdef HAVE_GL_GL_H
50 # include <GL/gl.h>
51 #endif
52 #undef RED
53 
54 #include "tk.h"
55 #include "tkPlatDecls.h"
56 #include "bu/color.h"
57 #include "bu/str.h"
58 #include "bu/parallel.h"
59 #include "rtgeom.h"
60 #include "raytrace.h"
61 #include "fb.h"
62 #include "fb_private.h"
63 #include "fb/fb_wgl.h"
64 
65 #define CJDEBUG 0
66 
67 /* XXX - arbitrary upper bound */
68 #define XMAXSCREEN 16383
69 #define YMAXSCREEN 16383
70 
71 /* Internal callbacks etc.*/
72 HIDDEN void wgl_do_event(fb *ifp);
73 HIDDEN void expose_callback(fb *ifp, int eventPtr);
74 
75 /* Other Internal routines */
76 HIDDEN void wgl_clipper(fb *ifp);
77 HIDDEN int wgl_getmem(fb *ifp);
78 HIDDEN void backbuffer_to_screen(fb *ifp, int one_y);
79 HIDDEN void wgl_cminit(fb *ifp);
80 HIDDEN PIXELFORMATDESCRIPTOR * wgl_choose_visual(fb *ifp);
81 HIDDEN int is_linear_cmap(fb *ifp);
82 
83 HIDDEN int wgl_nwindows = 0; /* number of open windows */
84 
85 
86 fb *saveifp;
87 int titleBarHeight = 0;
88 int borderWidth = 0;
89 
90 /*
91  * Structure of color map in shared memory region. Has exactly the
92  * same format as the SGI hardware "gammaramp" map Note that only the
93  * lower 8 bits are significant.
94  */
95 struct wgl_cmap {
96  short cmr[256];
97  short cmg[256];
98  short cmb[256];
99 };
100 
101 
102 /*
103  * This defines the format of the in-memory framebuffer copy. The
104  * alpha component and reverse order are maintained for compatibility
105  * with /dev/sgi
106  */
107 struct wgl_pixel {
108  unsigned char blue;
109  unsigned char green;
110  unsigned char red;
111  unsigned char alpha;
112 };
113 
114 
115 /* Clipping structure for zoom/pan operations */
116 struct wgl_clip {
117  int xpixmin; /* view clipping planes clipped to pixel memory space*/
118  int xpixmax;
119  int ypixmin;
120  int ypixmax;
121  int xscrmin; /* view clipping planes */
122  int xscrmax;
123  int yscrmin;
124  int yscrmax;
125  double oleft; /* glOrtho parameters */
126  double oright;
127  double otop;
128  double obottom;
129 };
130 
131 
132 /*
133  * Per window state information, overflow area.
134  */
135 struct sgiinfo {
136  short mi_curs_on;
137  short mi_cmap_flag; /* enabled when there is a non-linear map in memory */
138  int mi_shmid;
139  int mi_memwidth; /* width of scanline in if_mem */
140  short mi_xoff; /* X viewport offset, rel. window*/
141  short mi_yoff; /* Y viewport offset, rel. window*/
142  int mi_pid; /* for multi-cpu check */
143  int mi_parent; /* PID of linger-mode process */
144  int mi_doublebuffer; /* 0=singlebuffer 1=doublebuffer */
145  struct wgl_pixel mi_scanline[XMAXSCREEN+1]; /* one scanline */
146 };
147 
148 
149 /*
150  * Per window state information particular to the OpenGL interface
151  */
152 struct wglinfo {
153  HGLRC glxc;
154  Display *dispp; /* pointer to X display connection */
155  Window wind; /* Window identifier */
156  int firstTime;
157  int alive;
158  long event_mask; /* event types to be received */
159  short front_flag; /* front buffer being used (b-mode) */
160  short copy_flag; /* pan and zoom copied from backbuffer */
161  short soft_cmap_flag; /* use software colormapping */
162  int cmap_size; /* hardware colormap size */
163  int win_width; /* actual window width */
164  int win_height; /* actual window height */
165  int vp_width; /* actual viewport width */
166  int vp_height; /* actual viewport height */
167  struct wgl_clip clip; /* current view clipping */
168  Window cursor;
169  PIXELFORMATDESCRIPTOR *vip; /* pointer to info on current visual */
170  Colormap xcmap; /* xstyle color map */
171  int use_ext_ctrl; /* for controlling the Wgl graphics engine externally */
172  HDC hdc;
173  HWND hwnd;
174 
175 };
176 
177 
178 #define SGI(ptr) ((struct sgiinfo *)((ptr)->u1.p))
179 #define SGIL(ptr) ((ptr)->u1.p) /* left hand side version */
180 #define WGL(ptr) ((struct wglinfo *)((ptr)->u6.p))
181 #define WGLL(ptr) ((ptr)->u6.p) /* left hand side version */
182 #define if_mem u2.p /* shared memory pointer */
183 #define if_cmap u3.p /* color map in shared memory */
184 #define CMR(x) ((struct wgl_cmap *)((x)->if_cmap))->cmr
185 #define CMG(x) ((struct wgl_cmap *)((x)->if_cmap))->cmg
186 #define CMB(x) ((struct wgl_cmap *)((x)->if_cmap))->cmb
187 #define if_zoomflag u4.l /* zoom > 1 */
188 #define if_mode u5.l /* see MODE_* defines */
189 
190 #define MARGIN 4 /* # pixels margin to screen edge */
191 
192 #define CLIP_XTRA 1
193 
194 #define WIN_L (ifp->if_max_width - ifp->if_width - MARGIN)
195 #define WIN_T (ifp->if_max_height - ifp->if_height - MARGIN)
196 
197 /*
198  * The mode has several independent bits:
199  * SHARED -vs- MALLOC'ed memory for the image
200  * TRANSIENT -vs- LINGERING windows
201  * Windowed -vs- Centered Full screen
202  * Suppress dither -vs- dither
203  * Double -vs- Single buffered
204  * DrawPixels -vs- CopyPixels
205  */
206 #define MODE_1MASK (1<<0)
207 #define MODE_1SHARED (0<<0) /* Use Shared memory */
208 #define MODE_1MALLOC (1<<0) /* Use malloc memory */
209 
210 #define MODE_2MASK (1<<1)
211 #define MODE_2TRANSIENT (0<<1)
212 #define MODE_2LINGERING (1<<1) /* leave window up after closing*/
213 
214 #define MODE_4MASK (1<<3)
215 #define MODE_4NORMAL (0<<3) /* dither if it seems necessary */
216 #define MODE_4NODITH (1<<3) /* suppress any dithering */
217 
218 #define MODE_7MASK (1<<6)
219 #define MODE_7NORMAL (0<<6) /* install colormap in hardware if possible*/
220 #define MODE_7SWCMAP (1<<6) /* use software colormapping */
221 
222 #define MODE_9MASK (1<<8)
223 #define MODE_9NORMAL (0<<8) /* doublebuffer if possible */
224 #define MODE_9SINGLEBUF (1<<8) /* singlebuffer only */
225 
226 #define MODE_11MASK (1<<10)
227 #define MODE_11NORMAL (0<<10) /* always draw from mem. to window */
228 #define MODE_11COPY (1<<10) /* keep full image on back buffer */
229 
230 #define MODE_12MASK (1<<11)
231 #define MODE_12NORMAL (0<<11)
232 #define MODE_12DELAY_WRITES_TILL_FLUSH (1<<11)
233 /* and copy current view to front */
234 #define MODE_15MASK (1<<14)
235 #define MODE_15NORMAL (0<<14)
236 #define MODE_15ZAP (1<<14) /* zap the shared memory segment */
237 
238 HIDDEN struct modeflags {
239  char c;
240  long mask;
241  long value;
242  char *help;
243 } modeflags[] = {
244  { 'p', MODE_1MASK, MODE_1MALLOC,
245  "Private memory - else shared" },
246  { 'l', MODE_2MASK, MODE_2LINGERING,
247  "Lingering window" },
248  { 't', MODE_2MASK, MODE_2TRANSIENT,
249  "Transient window" },
250  { 'd', MODE_4MASK, MODE_4NODITH,
251  "Suppress dithering - else dither if not 24-bit buffer" },
252  { 'c', MODE_7MASK, MODE_7SWCMAP,
253  "Perform software colormap - else use hardware colormap if possible" },
254  { 's', MODE_9MASK, MODE_9SINGLEBUF,
255  "Single buffer - else double buffer if possible" },
256  { 'b', MODE_11MASK, MODE_11COPY,
257  "Fast pan and zoom using backbuffer copy - else normal " },
258  { 'D', MODE_12DELAY_WRITES_TILL_FLUSH, MODE_12DELAY_WRITES_TILL_FLUSH,
259  "Don't update screen until fb_flush() is called. (Double buffer sim)" },
260  { 'z', MODE_15MASK, MODE_15ZAP,
261  "Zap (free) shared memory. Can also be done with fbfree command" },
262  { '\0', 0, 0, "" }
263 };
264 
265 
266 /************************************************************************/
267 /******************* Shared Memory Support ******************************/
268 /************************************************************************/
269 
270 /*
271  * Because there is no hardware zoom or pan, we need to repaint the
272  * screen (with big pixels) to implement these operations. This means
273  * that the actual "contents" of the frame buffer need to be stored
274  * somewhere else. If possible, we allocate a shared memory segment
275  * to contain that image. This has several advantages, the most
276  * important being that when operating the display in 12-bit output
277  * mode, pixel-readbacks still give the full 24-bits of color. System
278  * V shared memory persists until explicitly killed, so this also
279  * means that in MEX mode, the previous contents of the frame buffer
280  * still exist, and can be again accessed, even though the MEX windows
281  * are transient, per-process.
282  *
283  * There are a few oddities, however. The worst is that System V will
284  * not allow the break (see sbrk(2)) to be set above a shared memory
285  * segment, and shmat(2) does not seem to allow the selection of any
286  * reasonable memory address (like 6 Mbytes up) for the shared memory.
287  * In the initial version of this routine, that prevented subsequent
288  * calls to malloc() from succeeding, quite a drawback. The
289  * work-around used here is to increase the current break to a large
290  * value, attach to the shared memory, and then return the break to
291  * its original value. This should allow most reasonable requests for
292  * memory to be satisfied. In special cases, the values used here
293  * might need to be increased.
294  */
295 HIDDEN int
296 wgl_getmem(fb *ifp)
297 {
298  int pixsize;
299  int size;
300  int i;
301  char *sp;
302  int new = 0;
303 
304  errno = 0;
305 
306  {
307  /* In this mode, only malloc as much memory as is needed. */
308  SGI(ifp)->mi_memwidth = ifp->if_width;
309  pixsize = ifp->if_height * ifp->if_width * sizeof(struct wgl_pixel);
310  size = pixsize + sizeof(struct wgl_cmap);
311 
312  sp = calloc(1, size);
313  if (sp == 0) {
314  fb_log("wgl_getmem: frame buffer memory malloc failed\n");
315  goto fail;
316  }
317  new = 1;
318  goto success;
319  }
320 
321 success:
322  ifp->if_mem = sp;
323  ifp->if_cmap = sp + pixsize; /* cmap at end of area */
324  i = CMB(ifp)[255]; /* try to deref last word */
325  CMB(ifp)[255] = i;
326 
327  /* Provide non-black colormap on creation of new shared mem */
328  if (new)
329  wgl_cminit(ifp);
330  return 0;
331 fail:
332  fb_log("wgl_getmem: Unable to attach to shared memory.\n");
333  if ((sp = calloc(1, size)) == NULL) {
334  fb_log("wgl_getmem: malloc failure\n");
335  return -1;
336  }
337  new = 1;
338  goto success;
339 }
340 
341 
342 void
343 wgl_zapmem(void)
344 {
345 }
346 
347 
348 HIDDEN void
349 sigkid(int UNUSED(pid))
350 {
351  exit(0);
352 }
353 
354 
355 /*
356  * Note: unlike sgi_xmit_scanlines, this function updates an arbitrary
357  * rectangle of the frame buffer
358  */
359 HIDDEN void
360 wgl_xmit_scanlines(fb *ifp, int ybase, int nlines, int xbase, int npix)
361 {
362  int y;
363  int n;
364  int sw_cmap; /* !0 => needs software color map */
365  struct wgl_clip *clp;
366 
367  /* Caller is expected to handle attaching context, etc. */
368 
369  clp = &(WGL(ifp)->clip);
370 
371  if (WGL(ifp)->soft_cmap_flag && SGI(ifp)->mi_cmap_flag) {
372  sw_cmap = 1;
373  } else {
374  sw_cmap = 0;
375  }
376 
377  if (xbase > clp->xpixmax || ybase > clp->ypixmax)
378  return;
379  if (xbase < clp->xpixmin)
380  xbase = clp->xpixmin;
381  if (ybase < clp->ypixmin)
382  ybase = clp->ypixmin;
383 
384  if ((xbase + npix -1) > clp->xpixmax)
385  npix = clp->xpixmax - xbase + 1;
386  if ((ybase + nlines - 1) > clp->ypixmax)
387  nlines = clp->ypixmax - ybase + 1;
388 
389  if (!WGL(ifp)->use_ext_ctrl) {
390  if (!WGL(ifp)->copy_flag) {
391  /*
392  * Blank out areas of the screen around the image, if
393  * exposed. In COPY mode, this is done in
394  * backbuffer_to_screen().
395  */
396 
397  /* Blank out area left of image */
398  glColor3b(0, 0, 0);
399  if (clp->xscrmin < 0) glRecti(
400  clp->xscrmin - CLIP_XTRA,
401  clp->yscrmin - CLIP_XTRA,
402  CLIP_XTRA,
403  clp->yscrmax + CLIP_XTRA);
404 
405  /* Blank out area below image */
406  if (clp->yscrmin < 0) glRecti(
407  clp->xscrmin - CLIP_XTRA,
408  clp->yscrmin - CLIP_XTRA,
409  clp->xscrmax + CLIP_XTRA,
410  CLIP_XTRA);
411 
412  /* Blank out area right of image */
413  if (clp->xscrmax >= ifp->if_width) glRecti(
414  ifp->if_width - CLIP_XTRA,
415  clp->yscrmin - CLIP_XTRA,
416  clp->xscrmax + CLIP_XTRA,
417  clp->yscrmax + CLIP_XTRA);
418 
419  /* Blank out area above image */
420  if (clp->yscrmax >= ifp->if_height) glRecti(
421  clp->xscrmin - CLIP_XTRA,
422  ifp->if_height- CLIP_XTRA,
423  clp->xscrmax + CLIP_XTRA,
424  clp->yscrmax + CLIP_XTRA);
425 
426  } else if (WGL(ifp)->front_flag) {
427  /* in COPY mode, always draw full sized image into
428  * backbuffer. backbuffer_to_screen() is used to update
429  * the front buffer
430  */
431  glDrawBuffer(GL_BACK);
432  WGL(ifp)->front_flag = 0;
433  glMatrixMode(GL_PROJECTION);
434  glPushMatrix(); /* store current view clipping matrix*/
435  glLoadIdentity();
436  glOrtho(-0.25, ((GLdouble) WGL(ifp)->vp_width)-0.25,
437  -0.25, ((GLdouble) WGL(ifp)->vp_height)-0.25,
438  -1.0, 1.0);
439  glPixelZoom(1.0, 1.0);
440  }
441  }
442 
443  if (sw_cmap) {
444  /* Software colormap each line as it's transmitted */
445  int x;
446  struct wgl_pixel *wglp;
447  struct wgl_pixel *op;
448 
449  y = ybase;
450  if (CJDEBUG) printf("Doing sw colormap xmit\n");
451  /* Perform software color mapping into temp scanline */
452  op = SGI(ifp)->mi_scanline;
453  for (n=nlines; n>0; n--, y++) {
454  wglp = (struct wgl_pixel *)&ifp->if_mem[
455  (y*SGI(ifp)->mi_memwidth)*
456  sizeof(struct wgl_pixel) ];
457  for (x=xbase+npix-1; x>=xbase; x--) {
458  op[x].red = CMR(ifp)[wglp[x].red];
459  op[x].green = CMG(ifp)[wglp[x].green];
460  op[x].blue = CMB(ifp)[wglp[x].blue];
461  }
462 
463  glPixelStorei(GL_UNPACK_SKIP_PIXELS, xbase);
464  glRasterPos2i(xbase, y);
465  glDrawPixels(npix, 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
466  (const GLvoid *) op);
467 
468  }
469 
470  } else {
471  /* No need for software colormapping */
472 
473  glPixelStorei(GL_UNPACK_ROW_LENGTH, SGI(ifp)->mi_memwidth);
474  glPixelStorei(GL_UNPACK_SKIP_PIXELS, xbase);
475  glPixelStorei(GL_UNPACK_SKIP_ROWS, ybase);
476 
477  glRasterPos2i(xbase, ybase);
478  glDrawPixels(npix, nlines, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
479  (const GLvoid *) ifp->if_mem);
480 
481  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
482  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
483  }
484 }
485 
486 
487 LONG WINAPI
488 MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
489 {
490  switch (uMsg) {
491  case WM_PAINT:
492  if (!WGL(saveifp)->use_ext_ctrl)
493  expose_callback(saveifp, 0);
494  break;
495  case WM_LBUTTONDOWN:
496  break;
497  case WM_RBUTTONDOWN:
498  break;
499  case WM_MBUTTONDOWN:
500  break;
501  case WM_CLOSE:
502  WGL(saveifp)->alive = -1;
503  break;
504  case WM_LBUTTONUP:
505  WGL(saveifp)->alive = 0;
506  break;
507  case WM_RBUTTONUP:
508  WGL(saveifp)->alive = 0;
509  break;
510  case WM_MBUTTONUP:
511  {
512  int x, y;
513  struct wgl_pixel *wglp;
514 
515  x = GET_X_LPARAM(lParam);
516  y = saveifp->if_height - GET_Y_LPARAM(lParam) - 1;
517 
518  if (x < 0 || y < 0) {
519  fb_log("No RGB (outside image viewport)\n");
520  break;
521  }
522 
523  wglp = (struct wgl_pixel *)&saveifp->if_mem[
524  (y*SGI(saveifp)->mi_memwidth)*
525  sizeof(struct wgl_pixel)];
526 
527  fb_log("At image (%d, %d), real RGB=(%3d %3d %3d)\n",
528  x, y, (int)wglp[x].red, (int)wglp[x].green, (int)wglp[x].blue);
529  }
530  break;
531  case WM_KEYDOWN:
532  break;
533  case WM_KEYUP:
534  WGL(saveifp)->alive = 0;
535  break;
536  case WM_SIZE:
537  /* WIP: unimplemented, intentional fall through */
538  default:
539  return DefWindowProc (hWnd, uMsg, wParam, lParam);
540  }
541 
542  return 1;
543 }
544 
545 
546 HIDDEN int
547 wgl_open(fb *ifp, const char *file, int width, int height)
548 {
549  static char title[128];
550  int mode, ret;
551  HWND hwnd;
552  HDC hdc;
553  HGLRC glxc;
554  HINSTANCE hinstance;
555  DWORD Dword;
556  WNDCLASS wndclass;
557 
558  FB_CK_FB(ifp);
559 
560  saveifp = ifp;
561 
562 
563  /*
564  * First, attempt to determine operating mode for this open, based
565  * upon the "unit number" or flags. file = "/dev/wgl###"
566  */
567  mode = MODE_2LINGERING;
568 
569  if (file != NULL) {
570  const char *cp;
571  char modebuf[80];
572  char *mp;
573  int alpha;
574  struct modeflags *mfp;
575 
576  if (bu_strncmp(file, ifp->if_name, strlen(ifp->if_name))) {
577  /* How did this happen? */
578  mode = 0;
579  } else {
580  /* Parse the options */
581  alpha = 0;
582  mp = &modebuf[0];
583  cp = &file[8];
584  while (*cp != '\0' && !isspace(*cp)) {
585  *mp++ = *cp; /* copy it to buffer */
586  if (isdigit(*cp)) {
587  cp++;
588  continue;
589  }
590  alpha++;
591  for (mfp = modeflags; mfp->c != '\0'; mfp++) {
592  if (mfp->c == *cp) {
593  mode = (mode&~mfp->mask)|mfp->value;
594  break;
595  }
596  }
597  if (mfp->c == '\0' && *cp != '-') {
598  fb_log("if_wgl: unknown option '%c' ignored\n", *cp);
599  }
600  cp++;
601  }
602  *mp = '\0';
603  if (!alpha)
604  mode |= atoi(modebuf);
605  }
606 
607  if ((mode & MODE_15MASK) == MODE_15ZAP) {
608  /* Only task: Attempt to release shared memory segment */
609  wgl_zapmem();
610  return -1;
611  }
612  }
613  ifp->if_mode = mode;
614 
615  /*
616  * Allocate extension memory sections, addressed by
617  * SGI(ifp)->mi_xxx and WGL(ifp)->xxx
618  */
619 
620  if ((SGIL(ifp) = (char *)calloc(1, sizeof(struct sgiinfo))) == NULL) {
621  fb_log("wgl_open: sgiinfo malloc failed\n");
622  return -1;
623  }
624  if ((WGLL(ifp) = (char *)calloc(1, sizeof(struct wglinfo))) == NULL) {
625  fb_log("wgl_open: wglinfo malloc failed\n");
626  return -1;
627  }
628 
629  SGI(ifp)->mi_shmid = -1; /* indicate no shared memory */
630 
631  /* the Silicon Graphics Library Window management routines use
632  * shared memory. This causes lots of problems when you want to
633  * pass a window structure to a child process. One hack to get
634  * around this is to immediately fork and create a child process
635  * and sleep until the child sends a kill signal to the parent
636  * process. (in FBCLOSE) This allows us to use the traditional fb
637  * utility programs as well as allow the frame buffer window to
638  * remain around until killed by the menu subsystem.
639  */
640 
641  /* use defaults if invalid width and height specified */
642  if (width <= 0)
643  width = ifp->if_width;
644  if (height <= 0)
645  height = ifp->if_height;
646  /* use max values if width and height are greater */
647  if (width > ifp->if_max_width)
648  width = ifp->if_max_width;
649  if (height > ifp->if_max_height)
650  height = ifp->if_max_height;
651 
652  ifp->if_width = width;
653  ifp->if_height = height;
654 
655  SGI(ifp)->mi_curs_on = 1;
656 
657  /* Build a descriptive window title bar */
658  (void)snprintf(title, 128, "BRL-CAD /dev/wgl %s, %s",
659  ((ifp->if_mode & MODE_2MASK) == MODE_2TRANSIENT) ?
660  "Transient Win":
661  "Lingering Win",
662  ((ifp->if_mode & MODE_1MASK) == MODE_1MALLOC) ?
663  "Private Mem" :
664  "Shared Mem");
665 
666  /* initialize window state variables before calling wgl_getmem */
667  ifp->if_zoomflag = 0;
668  ifp->if_xzoom = 1; /* for zoom fakeout */
669  ifp->if_yzoom = 1; /* for zoom fakeout */
670  ifp->if_xcenter = width/2;
671  ifp->if_ycenter = height/2;
672  SGI(ifp)->mi_pid = bu_process_id();
673 
674  /* Attach to shared memory, potentially with a screen repaint */
675  if (wgl_getmem(ifp) < 0)
676  return -1;
677 
678  /* Register the frame class */
679  wndclass.style = 0;
680  wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
681  wndclass.cbClsExtra = 0;
682  wndclass.cbWndExtra = 0;
683  wndclass.hInstance = Tk_GetHINSTANCE();
684  wndclass.hIcon = LoadIcon (Tk_GetHINSTANCE(), "Win OpenGL");
685  wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
686  wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
687  wndclass.lpszMenuName = "Win OpenGL";
688  wndclass.lpszClassName = "Win OpenGL";
689 
690  ret = RegisterClass (&wndclass);
691 
692  titleBarHeight = GetSystemMetrics(SM_CYCAPTION);
693  borderWidth = GetSystemMetrics(SM_CYFRAME);
694 
695  WGL(ifp)->hwnd = CreateWindow(
696  "Win OpenGL", /* pointer to registered class name */
697  title, /* pointer to window name */
698  WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, /* window style */
699  CW_USEDEFAULT, /* horizontal position of window */
700  CW_USEDEFAULT, /* vertical position of window */
701  ifp->if_width + 2 * borderWidth, /* window width */
702  ifp->if_height + titleBarHeight + 2 * borderWidth, /* window height */
703  NULL, /* handle to parent or owner window */
704  NULL, /* handle to menu or child-window identifier */
705  Tk_GetHINSTANCE(), /* handle to application instance */
706  NULL /* pointer to window-creation data */
707  );
708 
709  Dword = GetLastError();
710 
711  hinstance=Tk_GetHINSTANCE();
712  hwnd = WGL(ifp)->hwnd;
713  WGL(ifp)->hdc = GetDC(WGL(ifp)->hwnd);
714  hdc = WGL(ifp)->hdc;
715 
716 
717  /* Choose an appropriate visual. */
718  if ((WGL(ifp)->vip = wgl_choose_visual(ifp)) == NULL) {
719  fb_log("wgl_open: Couldn't find an appropriate visual. Exiting.\n");
720  return -1;
721  }
722 
723  WGL(ifp)->glxc = wglCreateContext(WGL(ifp)->hdc);
724  glxc = WGL(ifp)->glxc;
725 
726  /* count windows */
727  wgl_nwindows++;
728 
729  WGL(ifp)->alive = 1;
730  WGL(ifp)->firstTime = 1;
731 
732  ShowWindow(WGL(ifp)->hwnd, SW_SHOW);
733  UpdateWindow(WGL(ifp)->hwnd);
734 
735  /* Loop through events until first exposure event is processed */
736  while (WGL(ifp)->firstTime == 1)
737  wgl_do_event(ifp);
738 
739  return 0;
740 }
741 
743 wgl_get_fbps(uint32_t magic)
744 {
745  struct fb_platform_specific *fb_ps = NULL;
746  struct wgl_fb_info *data = NULL;
747  BU_GET(fb_ps, struct fb_platform_specific);
748  BU_GET(data, struct wgl_fb_info);
749  fb_ps->magic = magic;
750  fb_ps->data = data;
751  return fb_ps;
752 }
753 
754 
755 HIDDEN void
756 wgl_put_fbps(struct fb_platform_specific *fbps)
757 {
758  BU_CKMAG(fbps, FB_WGL_MAGIC, "wgl framebuffer");
759  BU_PUT(fbps->data, struct wgl_fb_info);
760  BU_PUT(fbps, struct fb_platform_specific);
761  return;
762 }
763 
764 int
765 _wgl_open_existing(fb *ifp,
766  Display *dpy,
767  Window win,
768  Colormap cmap,
769  PIXELFORMATDESCRIPTOR *vip,
770  HDC hdc,
771  int width,
772  int height,
773  HGLRC glxc,
774  int double_buffer,
775  int soft_cmap)
776 {
777 
778  /* XXX for now use private memory */
779  ifp->if_mode = MODE_1MALLOC;
780 
781  /*
782  * Allocate extension memory sections, addressed by
783  * SGI(ifp)->mi_xxx and WGL(ifp)->xxx
784  */
785 
786  if ((SGIL(ifp) = (char *)calloc(1, sizeof(struct sgiinfo))) == NULL) {
787  fb_log("wgl_open: sgiinfo malloc failed\n");
788  return -1;
789  }
790  if ((WGLL(ifp) = (char *)calloc(1, sizeof(struct wglinfo))) == NULL) {
791  fb_log("wgl_open: wglinfo malloc failed\n");
792  return -1;
793  }
794 
795  WGL(ifp)->use_ext_ctrl = 1;
796 
797  SGI(ifp)->mi_shmid = -1; /* indicate no shared memory */
798  ifp->if_width = ifp->if_max_width = width;
799  ifp->if_height = ifp->if_max_height = height;
800 
801  WGL(ifp)->win_width = WGL(ifp)->vp_width = width;
802  WGL(ifp)->win_height = WGL(ifp)->vp_height = height;
803 
804  SGI(ifp)->mi_curs_on = 1;
805 
806  /* initialize window state variables before calling wgl_getmem */
807  ifp->if_zoomflag = 0;
808  ifp->if_xzoom = 1; /* for zoom fakeout */
809  ifp->if_yzoom = 1; /* for zoom fakeout */
810  ifp->if_xcenter = width/2;
811  ifp->if_ycenter = height/2;
812  SGI(ifp)->mi_pid = bu_process_id();
813 
814  /* Attach to shared memory, potentially with a screen repaint */
815  if (wgl_getmem(ifp) < 0)
816  return -1;
817 
818  WGL(ifp)->dispp = dpy;
819  /* ifp->if_selfd = ConnectionNumber(WGL(ifp)->dispp); */
820 
821  WGL(ifp)->vip = vip;
822  WGL(ifp)->glxc = glxc;
823  SGI(ifp)->mi_cmap_flag = !is_linear_cmap(ifp);
824  WGL(ifp)->soft_cmap_flag = soft_cmap;
825  SGI(ifp)->mi_doublebuffer = double_buffer;
826  WGL(ifp)->xcmap = cmap;
827 
828  WGL(ifp)->wind = win;
829  WGL(ifp)->hdc = hdc;
830  ++wgl_nwindows;
831 
832  WGL(ifp)->alive = 1;
833  WGL(ifp)->firstTime = 1;
834 
835  wgl_clipper(ifp);
836 
837  return 0;
838 }
839 
840 
841 int
842 wgl_open_existing(fb *ifp, int width, int height, struct fb_platform_specific *fb_p)
843 {
844  struct wgl_fb_info *wgl_internal = (struct wgl_fb_info *)fb_p->data;
845  BU_CKMAG(fb_p, FB_WGL_MAGIC, "wgl framebuffer");
846  return _wgl_open_existing(ifp, wgl_internal->dpy, wgl_internal->win, wgl_internal->cmap,
847  wgl_internal->vip, wgl_internal->hdc, width, height,
848  wgl_internal->glxc, wgl_internal->double_buffer, wgl_internal->soft_cmap);
849  return 0;
850 }
851 
852 
853 HIDDEN int
854 wgl_final_close(fb *ifp)
855 {
856 
857  if (CJDEBUG) {
858  printf("wgl_final_close: All done...goodbye!\n");
859  }
860 
861  if (WGL(ifp)->glxc) {
862  wglDeleteContext(WGL(ifp)->glxc);
863  }
864  if (WGL(ifp)->hdc) {
865  ReleaseDC(WGL(ifp)->hwnd, WGL(ifp)->hdc);
866  }
867  DestroyWindow(WGL(ifp)->hwnd);
868 
869  if (SGIL(ifp) != NULL) {
870  /* free up memory associated with image */
871 
872  /* free private memory */
873  (void)free(ifp->if_mem);
874  /* free state information */
875  (void)free((char *)SGIL(ifp));
876  SGIL(ifp) = NULL;
877  }
878 
879  if (WGLL(ifp) != NULL) {
880  (void) free((char *)WGLL(ifp));
881  WGLL(ifp) = NULL;
882  }
883 
884  wgl_nwindows--;
885  return 0;
886 }
887 
888 
889 HIDDEN int
890 wgl_flush(fb *ifp)
891 {
892  if ((ifp->if_mode & MODE_12MASK) == MODE_12DELAY_WRITES_TILL_FLUSH) {
893 
894  if (wglMakeCurrent(WGL(ifp)->hdc, WGL(ifp)->glxc)==False) {
895  fb_log("Warning, wgl_flush: wglMakeCurrent unsuccessful.\n");
896  }
897 
898  /* Send entire in-memory buffer to the screen, all at once */
899  wgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
900  if (SGI(ifp)->mi_doublebuffer) {
901  SwapBuffers(WGL(ifp)->hdc);
902  } else {
903  if (WGL(ifp)->copy_flag) {
904  backbuffer_to_screen(ifp, -1);
905  }
906  }
907 
908  /* unattach context for other threads to use, also flushes */
909  wglMakeCurrent(NULL, NULL);
910  }
911  /* XFlush(WGL(ifp)->dispp); */
912  glFlush();
913  return 0;
914 }
915 
916 
917 HIDDEN int
918 wgl_close(fb *ifp)
919 {
920 
921  wgl_flush(ifp);
922 
923  /* only the last open window can linger -
924  * call final_close if not lingering
925  */
926  if (wgl_nwindows > 1 ||
927  (ifp->if_mode & MODE_2MASK) == MODE_2TRANSIENT)
928  return wgl_final_close(ifp);
929 
930  if (CJDEBUG)
931  printf("wgl_close: remaining open to linger awhile.\n");
932 
933  /*
934  * else:
935  *
936  * LINGER mode. Don't return to caller until user mouses "close"
937  * menu item. This may delay final processing in the calling
938  * function for some time, but the assumption is that the user
939  * wishes to compare this image with others.
940  *
941  * Since we plan to linger here, long after our invoker expected
942  * us to be gone, be certain that no file descriptors remain open
943  * to associate us with pipelines, network connections, etc., that
944  * were ALREADY ESTABLISHED before the point that fb_open() was
945  * called.
946  *
947  * The simple for i=0..20 loop will not work, because that smashes
948  * some window-manager files. Therefore, we content ourselves
949  * with eliminating stdin.
950  */
951  fclose(stdin);
952 
953  while (0 < WGL(ifp)->alive)
954  wgl_do_event(ifp);
955 
956  return 0;
957 }
958 
959 
960 int
961 wgl_close_existing(fb *ifp)
962 {
963  /*
964  if (WGL(ifp)->cursor)
965  XDestroyWindow(WGL(ifp)->dispp, WGL(ifp)->cursor);
966  */
967 
968  if (SGIL(ifp) != NULL) {
969  /* free up memory associated with image */
970  /* free private memory */
971  (void)free(ifp->if_mem);
972  /* free state information */
973  (void)free((char *)SGIL(ifp));
974  SGIL(ifp) = NULL;
975  }
976 
977  if (WGLL(ifp) != NULL) {
978  (void) free((char *)WGLL(ifp));
979  WGLL(ifp) = NULL;
980  }
981 
982  return 0;
983 }
984 
985 
986 /*
987  * Handle any pending input events
988  */
989 HIDDEN int
990 wgl_poll(fb *ifp)
991 {
992  wgl_do_event(ifp);
993 
994  if (WGL(ifp)->alive < 0)
995  return 1;
996  else
997  return 0;
998 }
999 
1000 
1001 /*
1002  * Free shared memory resources, and close.
1003  */
1004 HIDDEN int
1005 wgl_free(fb *ifp)
1006 {
1007  int ret;
1008 
1009  if (CJDEBUG) printf("entering wgl_free\n");
1010  /* Close the framebuffer */
1011  ret = wgl_final_close(ifp);
1012 
1013  if ((ifp->if_mode & MODE_1MASK) == MODE_1SHARED) {
1014  /* If shared mem, release the shared memory segment */
1015  wgl_zapmem();
1016  }
1017  return ret;
1018 }
1019 
1020 
1021 /**
1022  * pp is a pointer to beginning of memory segment
1023  */
1024 HIDDEN int
1025 wgl_clear(fb *ifp, unsigned char *pp)
1026 {
1027  struct wgl_pixel bg;
1028  struct wgl_pixel *wglp;
1029  int cnt;
1030  int y;
1031 
1032  if (CJDEBUG) printf("entering wgl_clear\n");
1033 
1034  /* Set clear colors */
1035  if (pp != RGBPIXEL_NULL) {
1036  bg.alpha = 0;
1037  bg.red = (pp)[RED];
1038  bg.green = (pp)[GRN];
1039  bg.blue = (pp)[BLU];
1040  } else {
1041  bg.alpha = 0;
1042  bg.red = 0;
1043  bg.green = 0;
1044  bg.blue = 0;
1045  }
1046 
1047  /* Flood rectangle in shared memory */
1048  for (y=0; y < ifp->if_height; y++) {
1049  wglp = (struct wgl_pixel *)&ifp->if_mem[
1050  (y*SGI(ifp)->mi_memwidth+0)*sizeof(struct wgl_pixel) ];
1051  for (cnt=ifp->if_width-1; cnt >= 0; cnt--) {
1052  *wglp++ = bg; /* struct copy */
1053  }
1054  }
1055 
1056  if (WGL(ifp)->use_ext_ctrl) {
1057  return 0;
1058  }
1059 
1060  if (wglMakeCurrent(WGL(ifp)->hdc, WGL(ifp)->glxc)==False) {
1061  fb_log("Warning, wgl_clear: wglMakeCurrent unsuccessful.\n");
1062  }
1063 
1064  if (pp != RGBPIXEL_NULL) {
1065  glClearColor(pp[RED]/255.0, pp[GRN]/255.0, pp[BLU]/255.0, 0.0);
1066  } else {
1067  glClearColor(0, 0, 0, 0);
1068  }
1069 
1070  if (WGL(ifp)->copy_flag) {
1071  /* COPY mode: clear both buffers */
1072  if (WGL(ifp)->front_flag) {
1073  glDrawBuffer(GL_BACK);
1074  glClear(GL_COLOR_BUFFER_BIT);
1075  glDrawBuffer(GL_FRONT);
1076  glClear(GL_COLOR_BUFFER_BIT);
1077  } else {
1078  glDrawBuffer(GL_FRONT);
1079  glClear(GL_COLOR_BUFFER_BIT);
1080  glDrawBuffer(GL_BACK);
1081  glClear(GL_COLOR_BUFFER_BIT);
1082  }
1083  } else {
1084  glClear(GL_COLOR_BUFFER_BIT);
1085  if (SGI(ifp)->mi_doublebuffer) {
1086  SwapBuffers(WGL(ifp)->hdc);
1087  }
1088  }
1089 
1090  /* unattach context for other threads to use */
1091  wglMakeCurrent(NULL, NULL);
1092 
1093  return 0;
1094 }
1095 
1096 
1097 HIDDEN int
1098 wgl_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
1099 {
1100  struct wgl_clip *clp;
1101 
1102  if (CJDEBUG) printf("entering wgl_view\n");
1103 
1104  if (xzoom < 1) xzoom = 1;
1105  if (yzoom < 1) yzoom = 1;
1106  if (ifp->if_xcenter == xcenter && ifp->if_ycenter == ycenter
1107  && ifp->if_xzoom == xzoom && ifp->if_yzoom == yzoom)
1108  return 0;
1109 
1110  if (xcenter < 0 || xcenter >= ifp->if_width)
1111  return -1;
1112  if (ycenter < 0 || ycenter >= ifp->if_height)
1113  return -1;
1114  if (xzoom >= ifp->if_width || yzoom >= ifp->if_height)
1115  return -1;
1116 
1117  ifp->if_xcenter = xcenter;
1118  ifp->if_ycenter = ycenter;
1119  ifp->if_xzoom = xzoom;
1120  ifp->if_yzoom = yzoom;
1121 
1122  if (ifp->if_xzoom > 1 || ifp->if_yzoom > 1)
1123  ifp->if_zoomflag = 1;
1124  else ifp->if_zoomflag = 0;
1125 
1126 
1127  if (WGL(ifp)->use_ext_ctrl) {
1128  wgl_clipper(ifp);
1129  } else {
1130  if (wglMakeCurrent(WGL(ifp)->hdc, WGL(ifp)->glxc)==False) {
1131  fb_log("Warning, wgl_view: wglMakeCurrent unsuccessful.\n");
1132  }
1133 
1134  /* Set clipping matrix and zoom level */
1135  glMatrixMode(GL_PROJECTION);
1136  if (WGL(ifp)->copy_flag && !WGL(ifp)->front_flag) {
1137  /* COPY mode - no changes to backbuffer copy - just
1138  * need to update front buffer
1139  */
1140  glPopMatrix();
1141  glDrawBuffer(GL_FRONT);
1142  WGL(ifp)->front_flag = 1;
1143  }
1144  glLoadIdentity();
1145 
1146  wgl_clipper(ifp);
1147  clp = &(WGL(ifp)->clip);
1148  glOrtho(clp->oleft, clp->oright, clp->obottom, clp->otop, -1.0, 1.0);
1149  glPixelZoom((float) ifp->if_xzoom, (float) ifp->if_yzoom);
1150 
1151  if (WGL(ifp)->copy_flag) {
1152  backbuffer_to_screen(ifp, -1);
1153  } else {
1154  wgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1155  if (SGI(ifp)->mi_doublebuffer) {
1156  SwapBuffers(WGL(ifp)->hdc);
1157  }
1158  }
1159 
1160  /* unattach context for other threads to use */
1161  wglMakeCurrent(NULL, NULL);
1162  }
1163 
1164  return 0;
1165 }
1166 
1167 
1168 HIDDEN int
1169 wgl_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
1170 {
1171  if (CJDEBUG) printf("entering wgl_getview\n");
1172 
1173  *xcenter = ifp->if_xcenter;
1174  *ycenter = ifp->if_ycenter;
1175  *xzoom = ifp->if_xzoom;
1176  *yzoom = ifp->if_yzoom;
1177 
1178  return 0;
1179 }
1180 
1181 
1182 /*
1183  * read count pixels into pixelp starting at x, y
1184  */
1185 HIDDEN int
1186 wgl_read(fb *ifp, int x, int y, unsigned char *pixelp, size_t count)
1187 {
1188  size_t n;
1189  size_t scan_count; /* # pix on this scanline */
1190  unsigned char *cp;
1191  int ret;
1192  struct wgl_pixel *wglp;
1193 
1194  if (CJDEBUG) printf("entering wgl_read\n");
1195 
1196  if (x < 0 || x >= ifp->if_width ||
1197  y < 0 || y >= ifp->if_height)
1198  return -1;
1199 
1200  ret = 0;
1201  cp = (unsigned char *)(pixelp);
1202 
1203  while (count) {
1204  if (y >= ifp->if_height)
1205  break;
1206 
1207  if (count >= (size_t)(ifp->if_width-x))
1208  scan_count = ifp->if_width-x;
1209  else
1210  scan_count = count;
1211 
1212  wglp = (struct wgl_pixel *)&ifp->if_mem[
1213  (y*SGI(ifp)->mi_memwidth+x)*sizeof(struct wgl_pixel) ];
1214 
1215  n = scan_count;
1216  while (n) {
1217  cp[RED] = wglp->red;
1218  cp[GRN] = wglp->green;
1219  cp[BLU] = wglp->blue;
1220  wglp++;
1221  cp += 3;
1222  n--;
1223  }
1224  ret += scan_count;
1225  count -= scan_count;
1226  x = 0;
1227  /* Advance upwards */
1228  if (++y >= ifp->if_height)
1229  break;
1230  }
1231  return ret;
1232 }
1233 
1234 
1235 /*
1236  * write count pixels from pixelp starting at xstart, ystart
1237  */
1238 HIDDEN int
1239 wgl_write(fb *ifp, int xstart, int ystart, const unsigned char *pixelp, size_t count)
1240 {
1241  size_t scan_count; /* # pix on this scanline */
1242  size_t pix_count; /* # pixels to send */
1243  unsigned char *cp;
1244  int ret;
1245  int ybase;
1246  int x;
1247  int y;
1248 
1249  if (CJDEBUG) printf("entering wgl_write\n");
1250 
1251  /* fast exit cases */
1252  pix_count = count;
1253  if (pix_count == 0)
1254  return 0; /* OK, no pixels transferred */
1255 
1256  x = xstart;
1257  ybase = y = ystart;
1258 
1259  if (x < 0 || x >= ifp->if_width ||
1260  y < 0 || y >= ifp->if_height)
1261  return -1;
1262 
1263  ret = 0;
1264  cp = (unsigned char *)(pixelp);
1265 
1266  while (pix_count) {
1267  unsigned int n;
1268  struct wgl_pixel *wglp;
1269 
1270  if (y >= ifp->if_height)
1271  break;
1272 
1273  if (pix_count >= (size_t)(ifp->if_width-x))
1274  scan_count = ifp->if_width-x;
1275  else
1276  scan_count = pix_count;
1277 
1278  wglp = (struct wgl_pixel *)&ifp->if_mem[
1279  (y*SGI(ifp)->mi_memwidth+x)*sizeof(struct wgl_pixel) ];
1280 
1281  n = scan_count;
1282  if ((n & 3) != 0) {
1283  /* This code uses 60% of all CPU time */
1284  while (n) {
1285  /* alpha channel is always zero */
1286  wglp->red = cp[RED];
1287  wglp->green = cp[GRN];
1288  wglp->blue = cp[BLU];
1289  wglp++;
1290  cp += 3;
1291  n--;
1292  }
1293  } else {
1294  while (n) {
1295  /* alpha channel is always zero */
1296  wglp[0].red = cp[RED+0*3];
1297  wglp[0].green = cp[GRN+0*3];
1298  wglp[0].blue = cp[BLU+0*3];
1299  wglp[1].red = cp[RED+1*3];
1300  wglp[1].green = cp[GRN+1*3];
1301  wglp[1].blue = cp[BLU+1*3];
1302  wglp[2].red = cp[RED+2*3];
1303  wglp[2].green = cp[GRN+2*3];
1304  wglp[2].blue = cp[BLU+2*3];
1305  wglp[3].red = cp[RED+3*3];
1306  wglp[3].green = cp[GRN+3*3];
1307  wglp[3].blue = cp[BLU+3*3];
1308  wglp += 4;
1309  cp += 3*4;
1310  n -= 4;
1311  }
1312  }
1313  ret += scan_count;
1314  pix_count -= scan_count;
1315  x = 0;
1316  if (++y >= ifp->if_height)
1317  break;
1318  }
1319 
1320  if ((ifp->if_mode & MODE_12MASK) == MODE_12DELAY_WRITES_TILL_FLUSH)
1321  return ret;
1322 
1323  if (!WGL(ifp)->use_ext_ctrl) {
1324 
1325  if (wglMakeCurrent(WGL(ifp)->hdc, WGL(ifp)->glxc)==False) {
1326  fb_log("Warning, wgl_write: wglMakeCurrent unsuccessful.\n");
1327  }
1328 
1329  if (xstart + count <= (size_t)ifp->if_width) {
1330  wgl_xmit_scanlines(ifp, ybase, 1, xstart, count);
1331  if (SGI(ifp)->mi_doublebuffer) {
1332  SwapBuffers(WGL(ifp)->hdc);
1333  } else if (WGL(ifp)->copy_flag) {
1334  /* repaint one scanline from backbuffer */
1335  backbuffer_to_screen(ifp, ybase);
1336  }
1337  } else {
1338  /* Normal case -- multi-pixel write */
1339  if (SGI(ifp)->mi_doublebuffer) {
1340  /* refresh whole screen */
1341  wgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1342  SwapBuffers(WGL(ifp)->hdc);
1343  } else {
1344  /* just write rectangle */
1345  wgl_xmit_scanlines(ifp, ybase, y-ybase, 0, ifp->if_width);
1346  if (WGL(ifp)->copy_flag) {
1347  backbuffer_to_screen(ifp, -1);
1348  }
1349  }
1350  }
1351 
1352  /* unattach context for other threads to use */
1353  wglMakeCurrent(NULL, NULL);
1354  }
1355 
1356  return ret;
1357 
1358 }
1359 
1360 
1361 /*
1362  * The task of this routine is to reformat the pixels into SGI
1363  * internal form, and then arrange to have them sent to the screen
1364  * separately.
1365  */
1366 HIDDEN int
1367 wgl_writerect(fb *ifp,
1368  int xmin,
1369  int ymin,
1370  int width,
1371  int height,
1372  const unsigned char *pp)
1373 {
1374  int x;
1375  int y;
1376  unsigned char *cp;
1377  struct wgl_pixel *wglp;
1378 
1379  if (CJDEBUG) printf("entering wgl_writerect\n");
1380 
1381 
1382  if (width <= 0 || height <= 0)
1383  return 0; /* do nothing */
1384  if (xmin < 0 || xmin+width > ifp->if_width ||
1385  ymin < 0 || ymin+height > ifp->if_height)
1386  return -1; /* no can do */
1387 
1388  cp = (unsigned char *)(pp);
1389  for (y = ymin; y < ymin+height; y++) {
1390  wglp = (struct wgl_pixel *)&ifp->if_mem[
1391  (y*SGI(ifp)->mi_memwidth+xmin)*sizeof(struct wgl_pixel) ];
1392  for (x = xmin; x < xmin+width; x++) {
1393  /* alpha channel is always zero */
1394  wglp->red = cp[RED];
1395  wglp->green = cp[GRN];
1396  wglp->blue = cp[BLU];
1397  wglp++;
1398  cp += 3;
1399  }
1400  }
1401 
1402  if ((ifp->if_mode & MODE_12MASK) == MODE_12DELAY_WRITES_TILL_FLUSH)
1403  return width*height;
1404 
1405  if (!WGL(ifp)->use_ext_ctrl) {
1406  if (wglMakeCurrent(WGL(ifp)->hdc, WGL(ifp)->glxc)==False) {
1407  fb_log("Warning, wgl_writerect: wglMakeCurrent unsuccessful.\n");
1408  }
1409 
1410  if (SGI(ifp)->mi_doublebuffer) {
1411  /* refresh whole screen */
1412  wgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1413  SwapBuffers(WGL(ifp)->hdc);
1414  } else {
1415  /* just write rectangle*/
1416  wgl_xmit_scanlines(ifp, ymin, height, xmin, width);
1417  if (WGL(ifp)->copy_flag) {
1418  backbuffer_to_screen(ifp, -1);
1419  }
1420  }
1421 
1422  /* unattach context for other threads to use */
1423  wglMakeCurrent(NULL, NULL);
1424  }
1425 
1426  return width*height;
1427 }
1428 
1429 
1430 /*
1431  * The task of this routine is to reformat the pixels into SGI
1432  * internal form, and then arrange to have them sent to the screen
1433  * separately.
1434  */
1435 HIDDEN int
1436 wgl_bwwriterect(fb *ifp,
1437  int xmin,
1438  int ymin,
1439  int width,
1440  int height,
1441  const unsigned char *pp)
1442 {
1443  int x;
1444  int y;
1445  unsigned char *cp;
1446  struct wgl_pixel *wglp;
1447 
1448  if (CJDEBUG) printf("entering wgl_bwwriterect\n");
1449 
1450 
1451  if (width <= 0 || height <= 0)
1452  return 0; /* do nothing */
1453  if (xmin < 0 || xmin+width > ifp->if_width ||
1454  ymin < 0 || ymin+height > ifp->if_height)
1455  return -1; /* no can do */
1456 
1457  cp = (unsigned char *)(pp);
1458  for (y = ymin; y < ymin+height; y++) {
1459  wglp = (struct wgl_pixel *)&ifp->if_mem[
1460  (y*SGI(ifp)->mi_memwidth+xmin)*sizeof(struct wgl_pixel) ];
1461  for (x = xmin; x < xmin+width; x++) {
1462  int val;
1463  /* alpha channel is always zero */
1464  wglp->red = (val = *cp++);
1465  wglp->green = val;
1466  wglp->blue = val;
1467  wglp++;
1468  }
1469  }
1470 
1471  if ((ifp->if_mode & MODE_12MASK) == MODE_12DELAY_WRITES_TILL_FLUSH)
1472  return width*height;
1473 
1474  if (!WGL(ifp)->use_ext_ctrl) {
1475  if (wglMakeCurrent(WGL(ifp)->hdc, WGL(ifp)->glxc)==False) {
1476  fb_log("Warning, wgl_writerect: wglMakeCurrent unsuccessful.\n");
1477  }
1478 
1479  if (SGI(ifp)->mi_doublebuffer) {
1480  /* refresh whole screen */
1481  wgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1482  SwapBuffers(WGL(ifp)->hdc);
1483  } else {
1484  /* just write rectangle*/
1485  wgl_xmit_scanlines(ifp, ymin, height, xmin, width);
1486  if (WGL(ifp)->copy_flag) {
1487  backbuffer_to_screen(ifp, -1);
1488  }
1489  }
1490 
1491  /* unattach context for other threads to use */
1492  wglMakeCurrent(NULL, NULL);
1493  }
1494 
1495  return width*height;
1496 }
1497 
1498 
1499 HIDDEN int
1500 wgl_rmap(fb *ifp, ColorMap *cmp)
1501 {
1502  int i;
1503 
1504  if (CJDEBUG) printf("entering wgl_rmap\n");
1505 
1506  /* Just parrot back the stored colormap */
1507  for (i = 0; i < 256; i++) {
1508  cmp->cm_red[i] = CMR(ifp)[i]<<8;
1509  cmp->cm_green[i] = CMG(ifp)[i]<<8;
1510  cmp->cm_blue[i] = CMB(ifp)[i]<<8;
1511  }
1512  return 0;
1513 }
1514 
1515 
1516 /*
1517  * Check for a color map being linear in R, G, and B. Returns 1 for
1518  * linear map, 0 for non-linear map (i.e., non-identity map).
1519  */
1520 HIDDEN int
1521 is_linear_cmap(fb *ifp)
1522 {
1523  int i;
1524 
1525  for (i=0; i<256; i++) {
1526  if (CMR(ifp)[i] != i) return 0;
1527  if (CMG(ifp)[i] != i) return 0;
1528  if (CMB(ifp)[i] != i) return 0;
1529  }
1530  return 1;
1531 }
1532 
1533 
1534 HIDDEN void
1535 wgl_cminit(fb *ifp)
1536 {
1537  int i;
1538 
1539  for (i = 0; i < 256; i++) {
1540  CMR(ifp)[i] = i;
1541  CMG(ifp)[i] = i;
1542  CMB(ifp)[i] = i;
1543  }
1544 }
1545 
1546 
1547 HIDDEN int
1548 wgl_wmap(fb *ifp, const ColorMap *cmp)
1549 {
1550  int i;
1551  int prev; /* !0 = previous cmap was non-linear */
1552 
1553  if (CJDEBUG) printf("entering wgl_wmap\n");
1554 
1555  prev = SGI(ifp)->mi_cmap_flag;
1556  if (cmp == COLORMAP_NULL) {
1557  wgl_cminit(ifp);
1558  } else {
1559  for (i = 0; i < 256; i++) {
1560  CMR(ifp)[i] = cmp-> cm_red[i]>>8;
1561  CMG(ifp)[i] = cmp-> cm_green[i]>>8;
1562  CMB(ifp)[i] = cmp-> cm_blue[i]>>8;
1563  }
1564  }
1565  SGI(ifp)->mi_cmap_flag = !is_linear_cmap(ifp);
1566 
1567 
1568  if (!WGL(ifp)->use_ext_ctrl) {
1569  if (WGL(ifp)->soft_cmap_flag) {
1570  /* if current and previous maps are linear, return */
1571  if (SGI(ifp)->mi_cmap_flag == 0 && prev == 0) return 0;
1572 
1573  /* Software color mapping, trigger a repaint */
1574 
1575  if (wglMakeCurrent(WGL(ifp)->hdc, WGL(ifp)->glxc)==False) {
1576  fb_log("Warning, wgl_wmap: wglMakeCurrent unsuccessful.\n");
1577  }
1578 
1579  wgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1580  if (SGI(ifp)->mi_doublebuffer) {
1581  SwapBuffers(WGL(ifp)->hdc);
1582  } else if (WGL(ifp)->copy_flag) {
1583  backbuffer_to_screen(ifp, -1);
1584  }
1585 
1586  /* unattach context for other threads to use, also flushes */
1587  wglMakeCurrent(NULL, NULL);
1588  } else {
1589  /* Send color map to hardware */
1590  }
1591  }
1592 
1593  return 0;
1594 }
1595 
1596 
1597 HIDDEN int
1598 wgl_help(fb *ifp)
1599 {
1600  struct modeflags *mfp;
1601 
1602  fb_log("Description: %s\n", ifp->if_type);
1603  fb_log("Device: %s\n", ifp->if_name);
1604  fb_log("Max width height: %d %d\n",
1605  ifp->if_max_width,
1606  ifp->if_max_height);
1607  fb_log("Default width height: %d %d\n",
1608  ifp->if_width,
1609  ifp->if_height);
1610  fb_log("Usage: /dev/wgl[option letters]\n");
1611  for (mfp = modeflags; mfp->c != '\0'; mfp++) {
1612  fb_log(" %c %s\n", mfp->c, mfp->help);
1613  }
1614 
1615  fb_log("\nCurrent internal state:\n");
1616  fb_log(" mi_doublebuffer=%d\n", SGI(ifp)->mi_doublebuffer);
1617  fb_log(" mi_cmap_flag=%d\n", SGI(ifp)->mi_cmap_flag);
1618  fb_log(" wgl_nwindows=%d\n", wgl_nwindows);
1619 
1620  return 0;
1621 }
1622 
1623 
1624 HIDDEN int
1625 wgl_setcursor(fb *ifp,
1626  const unsigned char *bits,
1627  int xbits,
1628  int ybits,
1629  int xorig,
1630  int yorig)
1631 {
1632  return 0;
1633 }
1634 
1635 
1636 HIDDEN int
1637 wgl_cursor(fb *ifp, int mode, int x, int y)
1638 {
1639  return 0;
1640 }
1641 
1642 
1643 /*
1644  * Given:
1645  * - the size of the viewport in pixels (vp_width, vp_height)
1646  * - the size of the framebuffer image (if_width, if_height)
1647  * - the current view center (if_xcenter, if_ycenter)
1648  * - the current zoom (if_xzoom, if_yzoom)
1649  *
1650  * Calculate:
1651  * - the position of the viewport in image space
1652  * (xscrmin, xscrmax, yscrmin, yscrmax)
1653  * - the portion of the image which is visible in the viewport
1654  * (xpixmin, xpixmax, ypixmin, ypixmax)
1655  */
1656 HIDDEN void
1657 wgl_clipper(fb *ifp)
1658 {
1659  struct wgl_clip *clp;
1660  int i;
1661  double pixels;
1662 
1663  clp = &(WGL(ifp)->clip);
1664 
1665  i = WGL(ifp)->vp_width/(2*ifp->if_xzoom);
1666  clp->xscrmin = ifp->if_xcenter - i;
1667  i = WGL(ifp)->vp_width/ifp->if_xzoom;
1668  clp->xscrmax = clp->xscrmin + i;
1669  pixels = (double) i;
1670  clp->oleft = ((double) clp->xscrmin) - 0.25*pixels/((double) WGL(ifp)->vp_width);
1671  clp->oright = clp->oleft + pixels;
1672 
1673  i = WGL(ifp)->vp_height/(2*ifp->if_yzoom);
1674  clp->yscrmin = ifp->if_ycenter - i;
1675  i = WGL(ifp)->vp_height/ifp->if_yzoom;
1676  clp->yscrmax = clp->yscrmin + i;
1677  pixels = (double) i;
1678  clp->obottom = ((double) clp->yscrmin) - 0.25*pixels/((double) WGL(ifp)->vp_height);
1679  clp->otop = clp->obottom + pixels;
1680 
1681  clp->xpixmin = clp->xscrmin;
1682  clp->xpixmax = clp->xscrmax;
1683  clp->ypixmin = clp->yscrmin;
1684  clp->ypixmax = clp->yscrmax;
1685 
1686  if (clp->xpixmin < 0) {
1687  clp->xpixmin = 0;
1688  }
1689 
1690  if (clp->ypixmin < 0) {
1691  clp->ypixmin = 0;
1692  }
1693 
1694  /* In copy mode, the backbuffer copy image is limited to the
1695  * viewport size; use that for clipping. Otherwise, use size of
1696  * framebuffer memory segment
1697  */
1698  if (WGL(ifp)->copy_flag) {
1699  if (clp->xpixmax > WGL(ifp)->vp_width-1) {
1700  clp->xpixmax = WGL(ifp)->vp_width-1;
1701  }
1702  if (clp->ypixmax > WGL(ifp)->vp_height-1) {
1703  clp->ypixmax = WGL(ifp)->vp_height-1;
1704  }
1705  } else {
1706  if (clp->xpixmax > ifp->if_width-1) {
1707  clp->xpixmax = ifp->if_width-1;
1708  }
1709  if (clp->ypixmax > ifp->if_height-1) {
1710  clp->ypixmax = ifp->if_height-1;
1711  }
1712  }
1713 
1714 }
1715 
1716 
1717 /********************************/
1718 /* Call back routines and so on */
1719 /********************************/
1720 
1721 HIDDEN void
1722 wgl_do_event(fb *ifp)
1723 {
1724  MSG msg;
1725  BOOL bRet;
1726  /* Check and Dispatch any messages. */
1727 
1728  if ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
1729  if (bRet == -1) {
1730  /* handle the error and possibly exit */
1731  } else {
1732  TranslateMessage(&msg);
1733  DispatchMessage(&msg);
1734  }
1735  }
1736 }
1737 
1738 
1739 HIDDEN void
1740 expose_callback(fb *ifp, int eventPtr)
1741 {
1742  /* XWindowAttributes xwa; */
1743  struct wgl_clip *clp;
1744 
1745  if (CJDEBUG) fb_log("entering expose_callback()\n");
1746 
1747  if (wglMakeCurrent(WGL(ifp)->hdc, WGL(ifp)->glxc) == False) {
1748  fb_log("Warning, libfb/expose_callback: wglMakeCurrent unsuccessful.\n");
1749  }
1750 
1751  if (WGL(ifp)->firstTime) {
1752  WGL(ifp)->firstTime = 0;
1753 
1754  /* just in case the configuration is double buffered but
1755  * we want to pretend it's not
1756  */
1757 
1758  if (!SGI(ifp)->mi_doublebuffer) {
1759  glDrawBuffer(GL_FRONT);
1760  }
1761 
1762  if ((ifp->if_mode & MODE_4MASK) == MODE_4NODITH) {
1763  glDisable(GL_DITHER);
1764  }
1765 
1766  /* set copy mode if possible and requested */
1767  if (SGI(ifp)->mi_doublebuffer &&
1768  ((ifp->if_mode & MODE_11MASK)==MODE_11COPY)) {
1769  /* Copy mode only works if there are two buffers to
1770  * use. It conflicts with double buffering
1771  */
1772  WGL(ifp)->copy_flag = 1;
1773  SGI(ifp)->mi_doublebuffer = 0;
1774  WGL(ifp)->front_flag = 1;
1775  glDrawBuffer(GL_FRONT);
1776  } else {
1777  WGL(ifp)->copy_flag = 0;
1778  }
1779 
1780  WGL(ifp)->win_width=ifp->if_width;
1781  WGL(ifp)->win_height=ifp->if_height;
1782 
1783  /* clear entire window */
1784  glViewport(0, 0, WGL(ifp)->win_width, WGL(ifp)->win_height);
1785  glClearColor(0, 0, 0, 0);
1786  glClear(GL_COLOR_BUFFER_BIT);
1787 
1788  /* Set normal viewport size to minimum of actual window size
1789  * and requested framebuffer size
1790  */
1791  WGL(ifp)->vp_width = (WGL(ifp)->win_width < ifp->if_width) ?
1792  WGL(ifp)->win_width : ifp->if_width;
1793  WGL(ifp)->vp_height = (WGL(ifp)->win_height < ifp->if_height) ?
1794  WGL(ifp)->win_height : ifp->if_height;
1795  ifp->if_xcenter = WGL(ifp)->vp_width/2;
1796  ifp->if_ycenter = WGL(ifp)->vp_height/2;
1797 
1798  /* center viewport in window */
1799  SGI(ifp)->mi_xoff=(WGL(ifp)->win_width-WGL(ifp)->vp_width)/2;
1800  SGI(ifp)->mi_yoff=(WGL(ifp)->win_height-WGL(ifp)->vp_height)/2;
1801  glViewport(SGI(ifp)->mi_xoff,
1802  SGI(ifp)->mi_yoff,
1803  WGL(ifp)->vp_width,
1804  WGL(ifp)->vp_height);
1805  /* initialize clipping planes and zoom */
1806  wgl_clipper(ifp);
1807  clp = &(WGL(ifp)->clip);
1808  glMatrixMode(GL_PROJECTION);
1809  glLoadIdentity();
1810  glOrtho(clp->oleft, clp->oright, clp->obottom, clp->otop,
1811  -1.0, 1.0);
1812  glPixelZoom((float) ifp->if_xzoom, (float) ifp->if_yzoom);
1813  } else if ((WGL(ifp)->win_width > ifp->if_width) ||
1814  (WGL(ifp)->win_height > ifp->if_height)) {
1815  /* clear whole buffer if window larger than framebuffer */
1816  if (WGL(ifp)->copy_flag && !WGL(ifp)->front_flag) {
1817  glDrawBuffer(GL_FRONT);
1818  glViewport(0, 0, WGL(ifp)->win_width,
1819  WGL(ifp)->win_height);
1820  glClearColor(0, 0, 0, 0);
1821  glClear(GL_COLOR_BUFFER_BIT);
1822  glDrawBuffer(GL_BACK);
1823  } else {
1824  glViewport(0, 0, WGL(ifp)->win_width,
1825  WGL(ifp)->win_height);
1826  glClearColor(0, 0, 0, 0);
1827  glClear(GL_COLOR_BUFFER_BIT);
1828  }
1829  /* center viewport */
1830  glViewport(SGI(ifp)->mi_xoff,
1831  SGI(ifp)->mi_yoff,
1832  WGL(ifp)->vp_width,
1833  WGL(ifp)->vp_height);
1834  }
1835 
1836  /* repaint entire image */
1837  wgl_xmit_scanlines(ifp, 0, ifp->if_height, 0, ifp->if_width);
1838  if (SGI(ifp)->mi_doublebuffer) {
1839  SwapBuffers(WGL(ifp)->hdc);
1840  } else if (WGL(ifp)->copy_flag) {
1841  backbuffer_to_screen(ifp, -1);
1842  }
1843 
1844  if (CJDEBUG) {
1845  int dbb, db, view[4], getster, getaux;
1846  glGetIntegerv(GL_VIEWPORT, view);
1847  glGetIntegerv(GL_DOUBLEBUFFER, &dbb);
1848  glGetIntegerv(GL_DRAW_BUFFER, &db);
1849  fb_log("Viewport: x %d y %d width %d height %d\n", view[0],
1850  view[1], view[2], view[3]);
1851  fb_log("expose: double buffered: %d, draw buffer %d\n", dbb, db);
1852  fb_log("front %d\tback%d\n", GL_FRONT, GL_BACK);
1853  glGetIntegerv(GL_STEREO, &getster);
1854  glGetIntegerv(GL_AUX_BUFFERS, &getaux);
1855  fb_log("double %d, stereo %d, aux %d\n", dbb, getster, getaux);
1856  }
1857 
1858  /* unattach context for other threads to use */
1859  wglMakeCurrent(NULL, NULL);
1860 }
1861 
1862 
1863 int
1864 wgl_configureWindow(fb *ifp, int width, int height)
1865 {
1866  if (width == WGL(ifp)->win_width &&
1867  height == WGL(ifp)->win_height)
1868  return;
1869 
1870  ifp->if_width = ifp->if_max_width = width;
1871  ifp->if_height = ifp->if_max_height = height;
1872 
1873  WGL(ifp)->win_width = WGL(ifp)->vp_width = width;
1874  WGL(ifp)->win_height = WGL(ifp)->vp_height = height;
1875 
1876  ifp->if_zoomflag = 0;
1877  ifp->if_xzoom = 1;
1878  ifp->if_yzoom = 1;
1879  ifp->if_xcenter = width/2;
1880  ifp->if_ycenter = height/2;
1881 
1882  wgl_getmem(ifp);
1883  wgl_clipper(ifp);
1884 
1885  return 0;
1886 }
1887 
1888 
1889 /* BACKBUFFER_TO_SCREEN - copy pixels from copy on the backbuffer to
1890  * the front buffer. Do one scanline specified by one_y, or whole
1891  * screen if one_y equals -1.
1892  */
1893 HIDDEN void
1894 backbuffer_to_screen(fb *ifp, int one_y)
1895 {
1896  struct wgl_clip *clp;
1897 
1898  if (!(WGL(ifp)->front_flag)) {
1899  WGL(ifp)->front_flag = 1;
1900  glDrawBuffer(GL_FRONT);
1901  glMatrixMode(GL_PROJECTION);
1902  glPopMatrix();
1903  glPixelZoom((float) ifp->if_xzoom, (float) ifp->if_yzoom);
1904  }
1905 
1906  clp = &(WGL(ifp)->clip);
1907 
1908  if (one_y > clp->ypixmax) {
1909  return;
1910  } else if (one_y < 0) {
1911  /* do whole visible screen */
1912 
1913  /* Blank out area left of image */
1914  glColor3b(0, 0, 0);
1915  if (clp->xscrmin < 0) glRecti(
1916  clp->xscrmin - CLIP_XTRA,
1917  clp->yscrmin - CLIP_XTRA,
1918  CLIP_XTRA,
1919  clp->yscrmax + CLIP_XTRA);
1920 
1921  /* Blank out area below image */
1922  if (clp->yscrmin < 0) glRecti(
1923  clp->xscrmin - CLIP_XTRA,
1924  clp->yscrmin - CLIP_XTRA,
1925  clp->xscrmax + CLIP_XTRA,
1926  CLIP_XTRA);
1927 
1928  /* We are in copy mode, so we use vp_width rather than
1929  * if_width
1930  */
1931  /* Blank out area right of image */
1932  if (clp->xscrmax >= WGL(ifp)->vp_width) glRecti(
1933  ifp->if_width - CLIP_XTRA,
1934  clp->yscrmin - CLIP_XTRA,
1935  clp->xscrmax + CLIP_XTRA,
1936  clp->yscrmax + CLIP_XTRA);
1937 
1938  /* Blank out area above image */
1939  if (clp->yscrmax >= WGL(ifp)->vp_height) glRecti(
1940  clp->xscrmin - CLIP_XTRA,
1941  WGL(ifp)->vp_height - CLIP_XTRA,
1942  clp->xscrmax + CLIP_XTRA,
1943  clp->yscrmax + CLIP_XTRA);
1944 
1945  /* copy image from backbuffer */
1946  glRasterPos2i(clp->xpixmin, clp->ypixmin);
1947  glCopyPixels(SGI(ifp)->mi_xoff + clp->xpixmin,
1948  SGI(ifp)->mi_yoff + clp->ypixmin,
1949  clp->xpixmax - clp->xpixmin +1,
1950  clp->ypixmax - clp->ypixmin +1,
1951  GL_COLOR);
1952 
1953 
1954  } else if (one_y < clp->ypixmin) {
1955  return;
1956  } else {
1957  /* draw one scanline */
1958  glRasterPos2i(clp->xpixmin, one_y);
1959  glCopyPixels(SGI(ifp)->mi_xoff + clp->xpixmin,
1960  SGI(ifp)->mi_yoff + one_y,
1961  clp->xpixmax - clp->xpixmin +1,
1962  1,
1963  GL_COLOR);
1964  }
1965 }
1966 
1967 
1968 /*
1969  * Select an appropriate visual, and set flags.
1970  *
1971  * The user requires support for:
1972  * -OpenGL rendering in RGBA mode
1973  *
1974  * The user may desire support for:
1975  * -a single-buffered OpenGL context
1976  * -a double-buffered OpenGL context
1977  * -hardware colormapping (DirectColor)
1978  *
1979  * We first try to satisfy all requirements and desires. If that
1980  * fails, we remove the desires one at a time until we succeed or
1981  * until only requirements are left. If at any stage more than one
1982  * visual meets the current criteria, the visual with the greatest
1983  * depth is chosen.
1984  *
1985  * The following flags are set:
1986  * SGI(ifp)->mi_doublebuffer
1987  * WGL(ifp)->soft_cmap_flag
1988  *
1989  * Return NULL on failure.
1990  */
1991 HIDDEN PIXELFORMATDESCRIPTOR *
1992 wgl_choose_visual(fb *ifp)
1993 {
1994  int iPixelFormat;
1995  PIXELFORMATDESCRIPTOR pfd, *ppfd;
1996  BOOL good;
1997 
1998  ppfd = &pfd;
1999 
2000  iPixelFormat = GetPixelFormat(WGL(ifp)->hdc);
2001  ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
2002  ppfd->nVersion = 1;
2003  ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_TYPE_RGBA | PFD_STEREO;
2004  ppfd->iPixelType = PFD_TYPE_RGBA;
2005  ppfd->cColorBits = 24;
2006  ppfd->cRedBits = 0;
2007  ppfd->cRedShift = 0;
2008  ppfd->cGreenBits = 0;
2009  ppfd->cGreenShift = 0;
2010  ppfd->cBlueBits = 0;
2011  ppfd->cBlueShift = 0;
2012  ppfd->cAlphaBits = 0;
2013  ppfd->cAlphaShift = 0;
2014  ppfd->cAccumBits = 0;
2015  ppfd->cAccumRedBits = 0;
2016  ppfd->cAccumGreenBits = 0;
2017  ppfd->cAccumBlueBits = 0;
2018  ppfd->cAccumAlphaBits = 0;
2019  ppfd->cDepthBits = 32;
2020  ppfd->cStencilBits = 0;
2021  ppfd->cAuxBuffers = 0;
2022  ppfd->iLayerType = PFD_MAIN_PLANE;
2023  ppfd->bReserved = 0;
2024  ppfd->dwLayerMask = 0;
2025  ppfd->dwVisibleMask = 0;
2026  ppfd->dwDamageMask = 0;
2027 
2028  iPixelFormat = ChoosePixelFormat(WGL(ifp)->hdc, ppfd);
2029  good = SetPixelFormat(WGL(ifp)->hdc, iPixelFormat, ppfd);
2030 
2031 
2032  SGI(ifp)->mi_doublebuffer = 1;
2033  WGL(ifp)->soft_cmap_flag = 1;
2034 
2035  if (good) return ppfd;
2036  else return (PIXELFORMATDESCRIPTOR *)NULL;
2037 }
2038 
2039 
2040 int
2041 wgl_refresh(fb *ifp,
2042  int x,
2043  int y,
2044  int w,
2045  int h)
2046 {
2047  int mm;
2048  struct wgl_clip *clp;
2049 
2050  if (w < 0) {
2051  w = -w;
2052  x -= w;
2053  }
2054 
2055  if (h < 0) {
2056  h = -h;
2057  y -= h;
2058  }
2059 
2060  glGetIntegerv(GL_MATRIX_MODE, &mm);
2061  glMatrixMode(GL_PROJECTION);
2062  glPushMatrix();
2063  glLoadIdentity();
2064 
2065  wgl_clipper(ifp);
2066  clp = &(WGL(ifp)->clip);
2067  glOrtho(clp->oleft, clp->oright, clp->obottom, clp->otop, -1.0, 1.0);
2068  glPixelZoom((float) ifp->if_xzoom, (float) ifp->if_yzoom);
2069 
2070  glMatrixMode(GL_MODELVIEW);
2071  glPushMatrix();
2072  glLoadIdentity();
2073 
2074  glViewport(0, 0, WGL(ifp)->win_width, WGL(ifp)->win_height);
2075  wgl_xmit_scanlines(ifp, y, h, x, w);
2076  glMatrixMode(GL_PROJECTION);
2077  glPopMatrix();
2078  glMatrixMode(GL_MODELVIEW);
2079  glPopMatrix();
2080  glMatrixMode(mm);
2081 
2082  if (!WGL(ifp)->use_ext_ctrl) {
2083  glFlush();
2084  }
2085 
2086  return 0;
2087 }
2088 
2089 
2090 /* This is the ONLY thing that we normally "export" */
2091 fb wgl_interface =
2092 {
2093  0, /* magic number slot */
2094  FB_WGL_MAGIC,
2095  wgl_open, /* open device */
2096  wgl_open_existing,
2097  wgl_close_existing,
2098  wgl_get_fbps,
2099  wgl_put_fbps,
2100  wgl_close, /* close device */
2101  wgl_clear, /* clear device */
2102  wgl_read, /* read pixels */
2103  wgl_write, /* write pixels */
2104  wgl_rmap, /* read colormap */
2105  wgl_wmap, /* write colormap */
2106  wgl_view, /* set view */
2107  wgl_getview, /* get view */
2108  wgl_setcursor, /* define cursor */
2109  wgl_cursor, /* set cursor */
2110  fb_sim_getcursor, /* get cursor */
2111  fb_sim_readrect, /* read rectangle */
2112  wgl_writerect, /* write rectangle */
2114  wgl_bwwriterect, /* write rectangle */
2115  wgl_configureWindow,
2116  wgl_refresh,
2117  wgl_poll, /* process events */
2118  wgl_flush, /* flush output */
2119  wgl_free, /* free resources */
2120  wgl_help, /* help message */
2121  "Microsoft Windows OpenGL", /* device description */
2122  XMAXSCREEN+1, /* max width */
2123  YMAXSCREEN+1, /* max height */
2124  "/dev/wgl", /* short device name */
2125  512, /* default/current width */
2126  512, /* default/current height */
2127  -1, /* select file desc */
2128  -1, /* file descriptor */
2129  1, 1, /* zoom */
2130  256, 256, /* window center */
2131  0, 0, 0, /* cursor */
2132  PIXEL_NULL, /* page_base */
2133  PIXEL_NULL, /* page_curp */
2134  PIXEL_NULL, /* page_endp */
2135  -1, /* page_no */
2136  0, /* page_dirty */
2137  0L, /* page_curpos */
2138  0L, /* page_pixels */
2139  0, /* debug */
2140  250 /* refresh rate (from fbserv) */
2141 };
2142 
2143 
2144 #else
2145 
2146 /* quell empty-compilation unit warnings */
2147 static const int unused = 0;
2148 
2149 #endif /* IF_WGL */
2150 
2151 /*
2152  * Local Variables:
2153  * mode: C
2154  * tab-width: 8
2155  * indent-tabs-mode: t
2156  * c-file-style: "stroustrup"
2157  * End:
2158  * ex: shiftwidth=4 tabstop=8
2159  */
Definition: db_flip.c:35
#define COLORMAP_NULL
Definition: fb.h:91
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
long Display
Definition: dm_xvars.h:49
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
#define FB_WGL_MAGIC
Definition: magic.h:181
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
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
long Colormap
Definition: dm_xvars.h:51
#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
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
long Window
Definition: dm_xvars.h:50
#define RGBPIXEL_NULL
Definition: fb.h:90
ustring alpha
Definition: fb.h:82
uint32_t magic
Definition: fb.h:176
#define LONG
Definition: sscanf.c:56
int clip(fastf_t *, fastf_t *, fastf_t *, fastf_t *)
Definition: clip.c:66
#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
unsigned short cm_blue[256]
Definition: fb.h:85
#define GRN
Definition: color.h:40
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
int if_xcenter
pan position
Definition: fb_private.h:122