11 #include "gui-pinout-preview.h"
13 /* The Linux OpenGL ABI 1.0 spec requires that we define
14 * GL_GLEXT_PROTOTYPES before including gl.h or glx.h for extensions
15 * in order to get prototypes:
16 * http://www.opengl.org/registry/ABI/
19 #define GL_GLEXT_PROTOTYPES 1
20 #ifdef HAVE_OPENGL_GL_H
21 # include <OpenGL/gl.h>
26 #include <gtk/gtkgl.h>
27 #include "hid/common/hidgl.h"
29 #include "hid/common/draw_helpers.h"
30 #include "hid/common/trackball.h"
32 #ifdef HAVE_LIBDMALLOC
37 extern HID_DRAW ghid_graphics
;
38 extern HID_DRAW_CLASS ghid_graphics_class
;
40 static hidGC current_gc
= NULL
;
42 /* Sets gport->u_gc to the "right" GC to use (wrt mask or window)
44 #define USE_GC(gc) if (!use_gc(gc)) return
46 static enum mask_mode cur_mask
= HID_MASK_OFF
;
47 static GLfloat view_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
50 {0.0, 0.0, 0.0, 1.0}};
51 static GLfloat last_modelview_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
54 {0.0, 0.0, 0.0, 1.0}};
55 static int global_view_2d
= 1;
57 typedef struct render_priv
{
58 GdkGLConfig
*glconfig
;
61 int subcomposite_stencil_bit
;
62 char *current_colorname
;
63 double current_alpha_mult
;
64 GTimer
*time_since_expose
;
66 /* Feature for leading the user to a particular location */
67 guint lead_user_timeout
;
68 GTimer
*lead_user_timer
;
70 Coord lead_user_radius
;
75 hidgl_instance
*hidgl
;
79 typedef struct gtk_gc_struct
81 struct hidgl_gc_struct hidgl_gc
; /* Parent */
83 const char *colorname
;
89 static void draw_lead_user (hidGC gc
, render_priv
*priv
);
90 static void ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
);
93 #define BOARD_THICKNESS MM_TO_COORD(1.60)
94 #define MASK_COPPER_SPACING MM_TO_COORD(0.05)
95 #define SILK_MASK_SPACING MM_TO_COORD(0.01)
97 compute_depth (int group
)
99 static int last_depth_computed
= 0;
103 int min_copper_group
;
104 int max_copper_group
;
105 int num_copper_groups
;
106 int middle_copper_group
;
109 top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
110 bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
112 min_copper_group
= MIN (bottom_group
, top_group
);
113 max_copper_group
= MAX (bottom_group
, top_group
);
114 num_copper_groups
= max_copper_group
- min_copper_group
+ 1;
115 middle_copper_group
= min_copper_group
+ num_copper_groups
/ 2;
117 if (group
>= 0 && group
< max_group
) {
118 if (group
>= min_copper_group
&& group
<= max_copper_group
) {
119 /* XXX: IS THIS INCORRECT FOR REVERSED GROUP ORDERINGS? */
120 depth
= -(group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
;
125 } else if (SL_TYPE (group
) == SL_MASK
) {
126 if (SL_SIDE (group
) == SL_TOP_SIDE
) {
127 depth
= -((min_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
- MASK_COPPER_SPACING
);
129 depth
= -((max_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
+ MASK_COPPER_SPACING
);
131 } else if (SL_TYPE (group
) == SL_SILK
) {
132 if (SL_SIDE (group
) == SL_TOP_SIDE
) {
133 depth
= -((min_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
- MASK_COPPER_SPACING
- SILK_MASK_SPACING
);
135 depth
= -((max_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
+ MASK_COPPER_SPACING
+ SILK_MASK_SPACING
);
138 } else if (SL_TYPE (group
) == SL_INVISIBLE
) {
139 /* Same as silk, but for the back-side layer */
140 if (Settings
.ShowBottomSide
) {
141 depth
= -((min_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
- MASK_COPPER_SPACING
- SILK_MASK_SPACING
);
143 depth
= -((max_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
+ MASK_COPPER_SPACING
+ SILK_MASK_SPACING
);
145 } else if (SL_TYPE (group
) == SL_RATS
||
146 SL_TYPE (group
) == SL_PDRILL
||
147 SL_TYPE (group
) == SL_UDRILL
) {
148 /* Draw these at the depth we last rendered at */
149 depth
= last_depth_computed
;
150 } else if (SL_TYPE (group
) == SL_PASTE
||
151 SL_TYPE (group
) == SL_FAB
||
152 SL_TYPE (group
) == SL_ASSY
) {
153 /* Layer types we don't use, which draw.c asks us about, so
154 * we just return _something_ to avoid the warnign below. */
155 depth
= last_depth_computed
;
158 printf ("Unknown layer group to set depth for: %i\n", group
);
159 depth
= last_depth_computed
;
162 last_depth_computed
= depth
;
167 start_subcomposite (hidgl_instance
*hidgl
)
169 render_priv
*priv
= gport
->render_priv
;
172 /* Flush out any existing geoemtry to be rendered */
173 hidgl_flush_triangles (hidgl
);
175 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
176 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
178 stencil_bit
= hidgl_assign_clear_stencil_bit (hidgl
); /* Get a new (clean) bitplane to stencil with */
179 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
180 glStencilFunc (GL_GREATER
, stencil_bit
, stencil_bit
); /* Pass stencil test if our assigned bit is clear */
182 priv
->subcomposite_stencil_bit
= stencil_bit
;
186 end_subcomposite (hidgl_instance
*hidgl
)
188 render_priv
*priv
= gport
->render_priv
;
190 /* Flush out any existing geoemtry to be rendered */
191 hidgl_flush_triangles (hidgl
);
193 hidgl_return_stencil_bit (hidgl
, priv
->subcomposite_stencil_bit
); /* Relinquish any bitplane we previously used */
196 glStencilFunc (GL_ALWAYS
, 0, 0); /* Always pass stencil test */
197 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
199 priv
->subcomposite_stencil_bit
= 0;
204 ghid_set_layer (const char *name
, int group
, int empty
)
206 render_priv
*priv
= gport
->render_priv
;
207 hidgl_instance
*hidgl
= priv
->hidgl
;
210 if (idx
>= 0 && idx
< max_group
)
212 int n
= PCB
->LayerGroups
.Number
[group
];
213 for (idx
= 0; idx
< n
-1; idx
++)
215 int ni
= PCB
->LayerGroups
.Entries
[group
][idx
];
216 if (ni
>= 0 && ni
< max_copper_layer
+ EXTRA_LAYERS
217 && PCB
->Data
->Layer
[ni
].On
)
220 idx
= PCB
->LayerGroups
.Entries
[group
][idx
];
223 end_subcomposite (hidgl
);
224 start_subcomposite (hidgl
);
226 /* Drawing is already flushed by {start,end}_subcomposite */
227 hidgl_set_depth (compute_depth (group
));
229 if (idx
>= 0 && idx
< max_copper_layer
+ EXTRA_LAYERS
)
231 priv
->trans_lines
= true;
232 return PCB
->Data
->Layer
[idx
].On
;
237 switch (SL_TYPE (idx
))
240 return PCB
->InvisibleObjectsOn
;
243 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
246 priv
->trans_lines
= true;
248 return PCB
->ElementOn
;
257 priv
->trans_lines
= true;
267 render_priv
*priv
= gport
->render_priv
;
268 hidgl_instance
*hidgl
= priv
->hidgl
;
270 end_subcomposite (hidgl
);
274 ghid_destroy_gc (hidGC gc
)
276 hidgl_finish_gc (gc
);
283 render_priv
*priv
= gport
->render_priv
;
284 hidGC gc
= (hidGC
) g_new0 (struct gtk_gc_struct
, 1);
285 gtkGC gtk_gc
= (gtkGC
)gc
;
288 gc
->hid_draw
= &ghid_graphics
;
290 hidgl_init_gc (priv
->hidgl
, gc
);
292 gtk_gc
->colorname
= Settings
.BackgroundColor
;
293 gtk_gc
->alpha_mult
= 1.0;
299 ghid_draw_grid (hidGC gc
, BoxType
*drawn_area
)
301 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
304 if (gdk_color_parse (Settings
.GridColor
, &gport
->grid_color
))
306 gport
->grid_color
.red
^= gport
->bg_color
.red
;
307 gport
->grid_color
.green
^= gport
->bg_color
.green
;
308 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
311 glEnable (GL_COLOR_LOGIC_OP
);
314 glColor3f (gport
->grid_color
.red
/ 65535.,
315 gport
->grid_color
.green
/ 65535.,
316 gport
->grid_color
.blue
/ 65535.);
318 hidgl_draw_grid (gc
, drawn_area
);
320 glDisable (GL_COLOR_LOGIC_OP
);
324 ghid_draw_bg_image (void)
326 static GLuint texture_handle
= 0;
328 if (!ghidgui
->bg_pixbuf
)
331 if (texture_handle
== 0)
333 int width
= gdk_pixbuf_get_width (ghidgui
->bg_pixbuf
);
334 int height
= gdk_pixbuf_get_height (ghidgui
->bg_pixbuf
);
335 int rowstride
= gdk_pixbuf_get_rowstride (ghidgui
->bg_pixbuf
);
336 int bits_per_sample
= gdk_pixbuf_get_bits_per_sample (ghidgui
->bg_pixbuf
);
337 int n_channels
= gdk_pixbuf_get_n_channels (ghidgui
->bg_pixbuf
);
338 unsigned char *pixels
= gdk_pixbuf_get_pixels (ghidgui
->bg_pixbuf
);
340 g_warn_if_fail (bits_per_sample
== 8);
341 g_warn_if_fail (rowstride
== width
* n_channels
);
343 glGenTextures (1, &texture_handle
);
344 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
346 /* XXX: We should proabbly determine what the maxmimum texture supported is,
347 * and if our image is larger, shrink it down using GDK pixbuf routines
348 * rather than having it fail below.
351 glTexImage2D (GL_TEXTURE_2D
, 0, GL_RGB
, width
, height
, 0,
352 (n_channels
== 4) ? GL_RGBA
: GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
355 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
357 glTexEnvf (GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
358 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
359 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
360 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
361 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
362 glEnable (GL_TEXTURE_2D
);
364 /* Render a quad with the background as a texture */
367 glTexCoord2d (0., 0.);
368 glVertex3i (0, 0, 0);
369 glTexCoord2d (1., 0.);
370 glVertex3i (PCB
->MaxWidth
, 0, 0);
371 glTexCoord2d (1., 1.);
372 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, 0);
373 glTexCoord2d (0., 1.);
374 glVertex3i (0, PCB
->MaxHeight
, 0);
377 glDisable (GL_TEXTURE_2D
);
381 ghid_use_mask (enum mask_mode mode
)
383 render_priv
*priv
= gport
->render_priv
;
384 hidgl_instance
*hidgl
= priv
->hidgl
;
385 static int stencil_bit
= 0;
387 if (mode
== cur_mask
)
390 /* Flush out any existing geoemtry to be rendered */
391 hidgl_flush_triangles (hidgl
);
395 case HID_MASK_BEFORE
:
396 /* The HID asks not to receive this mask type, so warn if we get it */
397 g_return_if_reached ();
400 /* Write '1' to the stencil buffer where the solder-mask should not be drawn. */
401 glColorMask (0, 0, 0, 0); /* Disable writting in color buffer */
402 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
403 stencil_bit
= hidgl_assign_clear_stencil_bit (hidgl
); /* Get a new (clean) bitplane to stencil with */
404 glStencilFunc (GL_ALWAYS
, stencil_bit
, stencil_bit
); /* Always pass stencil test, write stencil_bit */
405 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
406 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
410 /* Drawing operations as masked to areas where the stencil buffer is '0' */
411 glColorMask (1, 1, 1, 1); /* Enable drawing of r, g, b & a */
412 glStencilFunc (GL_GEQUAL
, 0, stencil_bit
); /* Draw only where our bit of the stencil buffer is clear */
413 glStencilOp (GL_KEEP
, GL_KEEP
, GL_KEEP
); /* Stencil buffer read only */
417 /* Disable stenciling */
418 hidgl_return_stencil_bit (hidgl
, stencil_bit
); /* Relinquish any bitplane we previously used */
419 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
426 /* Config helper functions for when the user changes color preferences.
427 | set_special colors used in the gtkhid.
430 set_special_grid_color (void)
432 if (!gport
->colormap
)
434 gport
->grid_color
.red
^= gport
->bg_color
.red
;
435 gport
->grid_color
.green
^= gport
->bg_color
.green
;
436 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
440 ghid_set_special_colors (HID_Attribute
* ha
)
442 if (!ha
->name
|| !ha
->value
)
444 if (!strcmp (ha
->name
, "background-color"))
446 ghid_map_color_string (*(char **) ha
->value
, &gport
->bg_color
);
447 set_special_grid_color ();
449 else if (!strcmp (ha
->name
, "off-limit-color"))
451 ghid_map_color_string (*(char **) ha
->value
, &gport
->offlimits_color
);
453 else if (!strcmp (ha
->name
, "grid-color"))
455 ghid_map_color_string (*(char **) ha
->value
, &gport
->grid_color
);
456 set_special_grid_color ();
470 set_gl_color_for_gc (hidGC gc
)
472 gtkGC gtk_gc
= (gtkGC
)gc
;
473 render_priv
*priv
= gport
->render_priv
;
474 static void *cache
= NULL
;
479 if (priv
->current_colorname
!= NULL
&&
480 strcmp (priv
->current_colorname
, gtk_gc
->colorname
) == 0 &&
481 priv
->current_alpha_mult
== gtk_gc
->alpha_mult
)
484 free (priv
->current_colorname
);
485 priv
->current_colorname
= strdup (gtk_gc
->colorname
);
486 priv
->current_alpha_mult
= gtk_gc
->alpha_mult
;
488 if (gport
->colormap
== NULL
)
489 gport
->colormap
= gtk_widget_get_colormap (gport
->top_window
);
490 if (strcmp (gtk_gc
->colorname
, "erase") == 0)
492 r
= gport
->bg_color
.red
/ 65535.;
493 g
= gport
->bg_color
.green
/ 65535.;
494 b
= gport
->bg_color
.blue
/ 65535.;
497 else if (strcmp (gtk_gc
->colorname
, "drill") == 0)
499 r
= gport
->offlimits_color
.red
/ 65535.;
500 g
= gport
->offlimits_color
.green
/ 65535.;
501 b
= gport
->offlimits_color
.blue
/ 65535.;
506 if (hid_cache_color (0, gtk_gc
->colorname
, &cval
, &cache
))
507 cc
= (ColorCache
*) cval
.ptr
;
510 cc
= (ColorCache
*) malloc (sizeof (ColorCache
));
511 memset (cc
, 0, sizeof (*cc
));
513 hid_cache_color (1, gtk_gc
->colorname
, &cval
, &cache
);
518 if (gdk_color_parse (gtk_gc
->colorname
, &cc
->color
))
519 gdk_color_alloc (gport
->colormap
, &cc
->color
);
521 gdk_color_white (gport
->colormap
, &cc
->color
);
522 cc
->red
= cc
->color
.red
/ 65535.;
523 cc
->green
= cc
->color
.green
/ 65535.;
524 cc
->blue
= cc
->color
.blue
/ 65535.;
534 a
*= gtk_gc
->alpha_mult
;
535 if (!priv
->trans_lines
)
538 if (g
> maxi
) maxi
= g
;
539 if (b
> maxi
) maxi
= b
;
540 mult
= MIN (1 / a
, 1 / maxi
);
548 if(!priv
->in_context
)
551 hidgl_flush_triangles (gtk_gc
->hidgl_gc
.hidgl
);
552 glColor4d (r
, g
, b
, a
);
556 ghid_set_color (hidGC gc
, const char *name
)
558 gtkGC gtk_gc
= (gtkGC
)gc
;
560 gtk_gc
->colorname
= name
;
561 set_gl_color_for_gc (gc
);
565 ghid_set_alpha_mult (hidGC gc
, double alpha_mult
)
567 gtkGC gtk_gc
= (gtkGC
)gc
;
569 gtk_gc
->alpha_mult
= alpha_mult
;
570 set_gl_color_for_gc (gc
);
574 ghid_set_line_cap (hidGC gc
, EndCapStyle style
)
576 gtkGC gtk_gc
= (gtkGC
)gc
;
582 ghid_set_line_width (hidGC gc
, Coord width
)
584 gtkGC gtk_gc
= (gtkGC
)gc
;
586 gtk_gc
->width
= width
;
591 ghid_set_draw_xor (hidGC gc
, int xor)
593 /* NOT IMPLEMENTED */
595 /* Only presently called when setting up a crosshair GC.
596 * We manage our own drawing model for that anyway. */
600 ghid_set_draw_faded (hidGC gc
, int faded
)
602 printf ("ghid_set_draw_faded(%p,%d) -- not implemented\n", gc
, faded
);
606 ghid_set_line_cap_angle (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
608 printf ("ghid_set_line_cap_angle() -- not implemented\n");
612 ghid_invalidate_current_gc (void)
620 if (gc
->hid
!= &ghid_hid
)
622 fprintf (stderr
, "Fatal: GC from another HID passed to GTK HID\n");
626 if (current_gc
== gc
)
631 set_gl_color_for_gc (gc
);
636 ghid_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
638 gtkGC gtk_gc
= (gtkGC
)gc
;
641 hidgl_draw_line (gc
, gtk_gc
->cap
, gtk_gc
->width
, x1
, y1
, x2
, y2
, gport
->view
.coord_per_px
);
645 ghid_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord xradius
, Coord yradius
,
646 Angle start_angle
, Angle delta_angle
)
648 gtkGC gtk_gc
= (gtkGC
)gc
;
651 hidgl_draw_arc (gc
, gtk_gc
->width
, cx
, cy
, xradius
, yradius
,
652 start_angle
, delta_angle
, gport
->view
.coord_per_px
);
656 ghid_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
660 hidgl_draw_rect (gc
, x1
, y1
, x2
, y2
);
665 ghid_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
669 hidgl_fill_circle (gc
, cx
, cy
, radius
, gport
->view
.coord_per_px
);
674 ghid_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
678 hidgl_fill_polygon (gc
, n_coords
, x
, y
);
682 ghid_fill_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
686 hidgl_fill_pcb_polygon (gc
, poly
, clip_box
, gport
->view
.coord_per_px
);
690 ghid_thindraw_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
692 common_thindraw_pcb_polygon (gc
, poly
, clip_box
);
693 ghid_set_alpha_mult (gc
, 0.25);
694 hid_draw_fill_pcb_polygon (gc
, poly
, clip_box
);
695 ghid_set_alpha_mult (gc
, 1.0);
699 ghid_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
703 hidgl_fill_rect (gc
, x1
, y1
, x2
, y2
);
707 ghid_invalidate_lr (int left
, int right
, int top
, int bottom
)
709 ghid_invalidate_all ();
712 #define MAX_ELAPSED (50. / 1000.) /* 50ms */
714 ghid_invalidate_all ()
716 render_priv
*priv
= gport
->render_priv
;
717 double elapsed
= g_timer_elapsed (priv
->time_since_expose
, NULL
);
719 ghid_draw_area_update (gport
, NULL
);
721 if (elapsed
> MAX_ELAPSED
)
722 gdk_window_process_all_updates ();
726 ghid_notify_crosshair_change (bool changes_complete
)
728 /* We sometimes get called before the GUI is up */
729 if (gport
->drawing_area
== NULL
)
732 /* FIXME: We could just invalidate the bounds of the crosshair attached objects? */
733 ghid_invalidate_all ();
737 ghid_notify_mark_change (bool changes_complete
)
739 /* We sometimes get called before the GUI is up */
740 if (gport
->drawing_area
== NULL
)
743 /* FIXME: We could just invalidate the bounds of the mark? */
744 ghid_invalidate_all ();
748 draw_right_cross (gint x
, gint y
, gint z
)
750 glVertex3i (x
, 0, z
);
751 glVertex3i (x
, PCB
->MaxHeight
, z
);
752 glVertex3i (0, y
, z
);
753 glVertex3i (PCB
->MaxWidth
, y
, z
);
757 draw_slanted_cross (gint x
, gint y
, gint z
)
761 x0
= x
+ (PCB
->MaxHeight
- y
);
762 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
764 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
765 y0
= y
+ (PCB
->MaxWidth
- x
);
766 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
768 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
769 glVertex3i (x0
, y0
, z
);
770 glVertex3i (x1
, y1
, z
);
772 x0
= x
- (PCB
->MaxHeight
- y
);
773 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
775 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
777 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
778 y1
= y
- (PCB
->MaxWidth
- x
);
779 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
780 glVertex3i (x0
, y0
, z
);
781 glVertex3i (x1
, y1
, z
);
785 draw_dozen_cross (gint x
, gint y
, gint z
)
788 gdouble tan60
= sqrt (3);
790 x0
= x
+ (PCB
->MaxHeight
- y
) / tan60
;
791 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
793 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
794 y0
= y
+ (PCB
->MaxWidth
- x
) * tan60
;
795 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
797 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
798 glVertex3i (x0
, y0
, z
);
799 glVertex3i (x1
, y1
, z
);
801 x0
= x
+ (PCB
->MaxHeight
- y
) * tan60
;
802 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
804 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
805 y0
= y
+ (PCB
->MaxWidth
- x
) / tan60
;
806 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
808 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
809 glVertex3i (x0
, y0
, z
);
810 glVertex3i (x1
, y1
, z
);
812 x0
= x
- (PCB
->MaxHeight
- y
) / tan60
;
813 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
815 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
817 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
818 y1
= y
- (PCB
->MaxWidth
- x
) * tan60
;
819 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
820 glVertex3i (x0
, y0
, z
);
821 glVertex3i (x1
, y1
, z
);
823 x0
= x
- (PCB
->MaxHeight
- y
) * tan60
;
824 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
826 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
828 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
829 y1
= y
- (PCB
->MaxWidth
- x
) / tan60
;
830 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
831 glVertex3i (x0
, y0
, z
);
832 glVertex3i (x1
, y1
, z
);
836 draw_crosshair (render_priv
*priv
)
839 static int done_once
= 0;
840 static GdkColor cross_color
;
845 /* FIXME: when CrossColor changed from config */
846 ghid_map_color_string (Settings
.CrossColor
, &cross_color
);
849 x
= gport
->crosshair_x
;
850 y
= gport
->crosshair_y
;
853 glEnable (GL_COLOR_LOGIC_OP
);
856 glColor3f (cross_color
.red
/ 65535.,
857 cross_color
.green
/ 65535.,
858 cross_color
.blue
/ 65535.);
862 draw_right_cross (x
, y
, z
);
863 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
864 draw_slanted_cross (x
, y
, z
);
865 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
866 draw_dozen_cross (x
, y
, z
);
870 glDisable (GL_COLOR_LOGIC_OP
);
874 ghid_init_renderer (int *argc
, char ***argv
, GHidPort
*port
)
878 port
->render_priv
= priv
= g_new0 (render_priv
, 1);
880 priv
->time_since_expose
= g_timer_new ();
882 gtk_gl_init(argc
, argv
);
884 /* setup GL-context */
885 priv
->glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA
|
886 GDK_GL_MODE_STENCIL
|
890 printf ("Could not setup GL-context!\n");
891 return; /* Should we abort? */
895 priv
->hidgl
= hidgl_new_instance ();
896 port
->render_priv
->crosshair_gc
= hid_draw_make_gc (&ghid_graphics
);
898 /* Setup HID function pointers specific to the GL renderer*/
899 ghid_graphics_class
.end_layer
= ghid_end_layer
;
900 ghid_graphics_class
.fill_pcb_polygon
= ghid_fill_pcb_polygon
;
901 ghid_graphics_class
.thindraw_pcb_polygon
= ghid_thindraw_pcb_polygon
;
905 ghid_shutdown_renderer (GHidPort
*port
)
907 render_priv
*priv
= port
->render_priv
;
909 hid_draw_destroy_gc (priv
->crosshair_gc
);
910 hidgl_free_instance (priv
->hidgl
);
912 ghid_cancel_lead_user ();
913 g_free (port
->render_priv
);
914 port
->render_priv
= NULL
;
918 ghid_init_drawing_widget (GtkWidget
*widget
, GHidPort
*port
)
920 render_priv
*priv
= port
->render_priv
;
922 gtk_widget_set_gl_capability (widget
,
930 ghid_drawing_area_configure_hook (GHidPort
*port
)
935 ghid_start_drawing (GHidPort
*port
, GtkWidget
*widget
)
937 GdkGLContext
*pGlContext
= gtk_widget_get_gl_context (widget
);
938 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
940 /* make GL-context "current" */
941 if (!gdk_gl_drawable_gl_begin (pGlDrawable
, pGlContext
))
944 port
->render_priv
->in_context
= true;
946 hidgl_start_render (port
->render_priv
->hidgl
);
952 ghid_end_drawing (GHidPort
*port
, GtkWidget
*widget
)
954 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
956 hidgl_finish_render (port
->render_priv
->hidgl
);
958 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
959 gdk_gl_drawable_swap_buffers (pGlDrawable
);
963 port
->render_priv
->in_context
= false;
965 /* end drawing to current GL-context */
966 gdk_gl_drawable_gl_end (pGlDrawable
);
970 ghid_screen_update (void)
976 ghid_drawing_area_expose_cb (GtkWidget
*widget
,
980 render_priv
*priv
= port
->render_priv
;
981 GtkAllocation allocation
;
989 gtk_widget_get_allocation (widget
, &allocation
);
991 ghid_start_drawing (port
, widget
);
993 /* If we don't have any stencil bits available,
994 we can't use the hidgl polygon drawing routine */
995 /* TODO: We could use the GLU tessellator though */
996 if (hidgl_stencil_bits (priv
->hidgl
) == 0)
997 ghid_graphics_class
.fill_pcb_polygon
= common_fill_pcb_polygon
;
1000 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1002 glViewport (0, 0, allocation
.width
, allocation
.height
);
1004 glEnable (GL_SCISSOR_TEST
);
1005 glScissor (ev
->area
.x
,
1006 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
1007 ev
->area
.width
, ev
->area
.height
);
1009 glMatrixMode (GL_PROJECTION
);
1011 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
1012 glMatrixMode (GL_MODELVIEW
);
1014 glTranslatef (widget
->allocation
.width
/ 2., widget
->allocation
.height
/ 2., 0);
1015 glMultMatrixf ((GLfloat
*)view_matrix
);
1016 glTranslatef (-widget
->allocation
.width
/ 2., -widget
->allocation
.height
/ 2., 0);
1017 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
1018 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
1019 ((port
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / port
->view
.coord_per_px
);
1020 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
1022 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
1024 glGetFloatv (GL_MODELVIEW_MATRIX
, (GLfloat
*)last_modelview_matrix
);
1026 glEnable (GL_STENCIL_TEST
);
1027 glClearColor (port
->offlimits_color
.red
/ 65535.,
1028 port
->offlimits_color
.green
/ 65535.,
1029 port
->offlimits_color
.blue
/ 65535.,
1033 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1034 hidgl_reset_stencil_usage (priv
->hidgl
);
1036 /* Disable the stencil test until we need it - otherwise it gets dirty */
1037 glDisable (GL_STENCIL_TEST
);
1039 glStencilFunc (GL_ALWAYS
, 0, 0);
1041 /* Test the 8 corners of a cube spanning the event */
1042 min_depth
= -50; /* FIXME */
1043 max_depth
= 0; /* FIXME */
1045 ghid_unproject_to_z_plane (ev
->area
.x
,
1047 min_depth
, &new_x
, &new_y
);
1048 max_x
= min_x
= new_x
;
1049 max_y
= min_y
= new_y
;
1051 ghid_unproject_to_z_plane (ev
->area
.x
,
1053 max_depth
, &new_x
, &new_y
);
1054 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1055 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1058 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
1060 min_depth
, &new_x
, &new_y
);
1061 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1062 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1064 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
, ev
->area
.y
,
1065 max_depth
, &new_x
, &new_y
);
1066 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1067 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1070 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
1071 ev
->area
.y
+ ev
->area
.height
,
1072 min_depth
, &new_x
, &new_y
);
1073 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1074 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1076 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
1077 ev
->area
.y
+ ev
->area
.height
,
1078 max_depth
, &new_x
, &new_y
);
1079 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1080 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1083 ghid_unproject_to_z_plane (ev
->area
.x
,
1084 ev
->area
.y
+ ev
->area
.height
,
1087 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1088 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1090 ghid_unproject_to_z_plane (ev
->area
.x
,
1091 ev
->area
.y
+ ev
->area
.height
,
1094 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1095 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1097 region
.X1
= min_x
; region
.X2
= max_x
+ 1;
1098 region
.Y1
= min_y
; region
.Y2
= max_y
+ 1;
1100 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
1101 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
1102 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
1103 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
1105 glColor3f (port
->bg_color
.red
/ 65535.,
1106 port
->bg_color
.green
/ 65535.,
1107 port
->bg_color
.blue
/ 65535.);
1110 glVertex3i (0, 0, -50);
1111 glVertex3i (PCB
->MaxWidth
, 0, -50);
1112 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, -50);
1113 glVertex3i (0, PCB
->MaxHeight
, -50);
1116 ghid_draw_bg_image ();
1118 ghid_invalidate_current_gc ();
1119 hid_expose_callback (&ghid_graphics
, ®ion
, 0);
1120 hidgl_flush_triangles (priv
->hidgl
);
1122 /* Set the current depth to the right value for the layer we are editing */
1123 hidgl_set_depth (compute_depth (GetLayerGroupNumberByNumber (INDEXOFCURRENT
)));
1125 ghid_draw_grid (priv
->crosshair_gc
, ®ion
);
1127 ghid_invalidate_current_gc ();
1129 DrawAttached (priv
->crosshair_gc
);
1130 DrawMark (priv
->crosshair_gc
);
1131 hidgl_flush_triangles (priv
->hidgl
);
1133 draw_crosshair (priv
);
1134 hidgl_flush_triangles (priv
->hidgl
);
1136 draw_lead_user (priv
->crosshair_gc
, priv
);
1138 ghid_end_drawing (port
, widget
);
1140 g_timer_start (priv
->time_since_expose
);
1145 /* This realize callback is used to work around a crash bug in some mesa
1146 * versions (observed on a machine running the intel i965 driver. It isn't
1147 * obvious why it helps, but somehow fiddling with the GL context here solves
1148 * the issue. The problem appears to have been fixed in recent mesa versions.
1151 ghid_port_drawing_realize_cb (GtkWidget
*widget
, gpointer data
)
1153 GdkGLContext
*glcontext
= gtk_widget_get_gl_context (widget
);
1154 GdkGLDrawable
*gldrawable
= gtk_widget_get_gl_drawable (widget
);
1156 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
))
1159 gdk_gl_drawable_gl_end (gldrawable
);
1164 ghid_pinout_preview_expose (GtkWidget
*widget
,
1167 GhidPinoutPreview
*pinout
= GHID_PINOUT_PREVIEW (widget
);
1168 render_priv
*priv
= gport
->render_priv
;
1169 GtkAllocation allocation
;
1170 view_data save_view
;
1171 int save_width
, save_height
;
1172 Coord save_max_width
;
1173 Coord save_max_height
;
1176 save_view
= gport
->view
;
1177 save_width
= gport
->width
;
1178 save_height
= gport
->height
;
1179 save_max_width
= PCB
->MaxWidth
;
1180 save_max_height
= PCB
->MaxHeight
;
1182 /* Setup zoom factor for drawing routines */
1184 gtk_widget_get_allocation (widget
, &allocation
);
1185 xz
= (double) pinout
->x_max
/ allocation
.width
;
1186 yz
= (double) pinout
->y_max
/ allocation
.height
;
1188 gport
->view
.coord_per_px
= xz
;
1190 gport
->view
.coord_per_px
= yz
;
1192 gport
->width
= allocation
.width
;
1193 gport
->height
= allocation
.height
;
1194 gport
->view
.width
= allocation
.width
* gport
->view
.coord_per_px
;
1195 gport
->view
.height
= allocation
.height
* gport
->view
.coord_per_px
;
1196 gport
->view
.x0
= (pinout
->x_max
- gport
->view
.width
) / 2;
1197 gport
->view
.y0
= (pinout
->y_max
- gport
->view
.height
) / 2;
1198 PCB
->MaxWidth
= pinout
->x_max
;
1199 PCB
->MaxHeight
= pinout
->y_max
;
1201 ghid_start_drawing (gport
, widget
);
1203 #if 0 /* We disable alpha blending here, as hid_expose_callback() does not
1204 * call set_layer() as appropriate for us to sub-composite rendering
1205 * from each layer when drawing a single element. If we leave alpha-
1206 * blending on, it means text and overlapping pads are rendered ugly.
1209 glEnable (GL_BLEND
);
1210 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1213 glViewport (0, 0, allocation
.width
, allocation
.height
);
1215 #if 0 /* We disable the scissor test here, as it is interacting badly with
1216 * being handed expose events which don't cover the whole window.
1217 * As we have a double-buffered GL window, we end up with unintialised
1218 * contents remaining in the unpainted areas (outside the scissor
1219 * region), and these are being flipped onto the screen.
1221 * The debugging code below shows multiple expose events when the
1222 * window is shown the first time, some of which are very small.
1224 * XXX: There is clearly a perforamnce issue here, in that we may
1225 * be rendering the preview more times, and over a larger area
1226 * than is really required.
1229 glEnable (GL_SCISSOR_TEST
);
1230 glScissor (ev
->area
.x
,
1231 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
1232 ev
->area
.width
, ev
->area
.height
);
1236 printf ("EVT: %i, %i, w=%i, h=%i, Scissor setup: glScissor (%f, %f, %f, %f);\n",
1237 ev
->area
.x
, ev
->area
.y
, ev
->area
.width
, ev
->area
.height
,
1239 (double)(allocation
.height
- ev
->area
.height
- ev
->area
.y
),
1240 (double)ev
->area
.width
,
1241 (double)ev
->area
.height
);
1244 glMatrixMode (GL_PROJECTION
);
1246 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
1247 glMatrixMode (GL_MODELVIEW
);
1249 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1251 glClearColor (gport
->bg_color
.red
/ 65535.,
1252 gport
->bg_color
.green
/ 65535.,
1253 gport
->bg_color
.blue
/ 65535.,
1257 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1258 hidgl_reset_stencil_usage (priv
->hidgl
);
1260 /* Disable the stencil test until we need it - otherwise it gets dirty */
1261 glDisable (GL_STENCIL_TEST
);
1263 glStencilFunc (GL_ALWAYS
, 0, 0);
1265 /* call the drawing routine */
1266 ghid_invalidate_current_gc ();
1268 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1269 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1270 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1271 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1273 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1274 -gport
->view
.y0
, 0);
1276 hidgl_set_depth (0.);
1277 hid_expose_callback (&ghid_graphics
, NULL
, pinout
->element
);
1278 hidgl_flush_triangles (priv
->hidgl
);
1281 ghid_end_drawing (gport
, widget
);
1283 gport
->view
= save_view
;
1284 gport
->width
= save_width
;
1285 gport
->height
= save_height
;
1286 PCB
->MaxWidth
= save_max_width
;
1287 PCB
->MaxHeight
= save_max_height
;
1294 ghid_render_pixmap (int cx
, int cy
, double zoom
, int width
, int height
, int depth
)
1296 render_priv
*priv
= gport
->render_priv
;
1297 GdkGLConfig
*glconfig
;
1299 GdkGLPixmap
*glpixmap
;
1300 GdkGLContext
* glcontext
;
1301 GdkGLDrawable
* gldrawable
;
1302 view_data save_view
;
1303 int save_width
, save_height
;
1306 save_view
= gport
->view
;
1307 save_width
= gport
->width
;
1308 save_height
= gport
->height
;
1310 /* Setup rendering context for drawing routines
1313 glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB
|
1314 GDK_GL_MODE_STENCIL
|
1315 GDK_GL_MODE_SINGLE
);
1317 pixmap
= gdk_pixmap_new (NULL
, width
, height
, depth
);
1318 glpixmap
= gdk_pixmap_set_gl_capability (pixmap
, glconfig
, NULL
);
1319 gldrawable
= GDK_GL_DRAWABLE (glpixmap
);
1320 glcontext
= gdk_gl_context_new (gldrawable
, NULL
, TRUE
, GDK_GL_RGBA_TYPE
);
1322 /* Setup zoom factor for drawing routines */
1324 gport
->view
.coord_per_px
= zoom
;
1325 gport
->width
= width
;
1326 gport
->height
= height
;
1327 gport
->view
.width
= width
* gport
->view
.coord_per_px
;
1328 gport
->view
.height
= height
* gport
->view
.coord_per_px
;
1329 gport
->view
.x0
= gport
->view
.flip_x
? PCB
->MaxWidth
- cx
: cx
;
1330 gport
->view
.x0
-= gport
->view
.height
/ 2;
1331 gport
->view
.y0
= gport
->view
.flip_y
? PCB
->MaxHeight
- cy
: cy
;
1332 gport
->view
.y0
-= gport
->view
.width
/ 2;
1334 /* make GL-context "current" */
1335 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
)) {
1338 hidgl_start_render (priv
->hidgl
);
1339 gport
->render_priv
->in_context
= true;
1341 glEnable (GL_BLEND
);
1342 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1344 glViewport (0, 0, width
, height
);
1346 glEnable (GL_SCISSOR_TEST
);
1347 glScissor (0, 0, width
, height
);
1349 glMatrixMode (GL_PROJECTION
);
1351 glOrtho (0, width
, height
, 0, -100000, 100000);
1352 glMatrixMode (GL_MODELVIEW
);
1354 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1356 glClearColor (gport
->bg_color
.red
/ 65535.,
1357 gport
->bg_color
.green
/ 65535.,
1358 gport
->bg_color
.blue
/ 65535.,
1362 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1363 hidgl_reset_stencil_usage (priv
->hidgl
);
1365 /* Disable the stencil test until we need it - otherwise it gets dirty */
1366 glDisable (GL_STENCIL_TEST
);
1368 glStencilFunc (GL_ALWAYS
, 0, 0);
1370 /* call the drawing routine */
1371 ghid_invalidate_current_gc ();
1373 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
1374 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
1375 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1376 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
1378 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
1379 -gport
->view
.y0
, 0);
1381 region
.X1
= MIN(Px(0), Px(gport
->width
+ 1));
1382 region
.Y1
= MIN(Py(0), Py(gport
->height
+ 1));
1383 region
.X2
= MAX(Px(0), Px(gport
->width
+ 1));
1384 region
.Y2
= MAX(Py(0), Py(gport
->height
+ 1));
1386 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
1387 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
1388 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
1389 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
1391 hid_expose_callback (&ghid_graphics
, ®ion
, NULL
);
1392 hidgl_flush_triangles (priv
->hidgl
);
1397 hidgl_finish_render (priv
->hidgl
);
1399 /* end drawing to current GL-context */
1400 gport
->render_priv
->in_context
= false;
1401 gdk_gl_drawable_gl_end (gldrawable
);
1403 gdk_pixmap_unset_gl_capability (pixmap
);
1405 g_object_unref (glconfig
);
1406 g_object_unref (glcontext
);
1408 gport
->view
= save_view
;
1409 gport
->width
= save_width
;
1410 gport
->height
= save_height
;
1416 ghid_request_debug_draw (void)
1418 GHidPort
*port
= gport
;
1419 GtkWidget
*widget
= port
->drawing_area
;
1420 GtkAllocation allocation
;
1422 gtk_widget_get_allocation (widget
, &allocation
);
1424 ghid_start_drawing (port
, widget
);
1426 glViewport (0, 0, allocation
.width
, allocation
.height
);
1428 glMatrixMode (GL_PROJECTION
);
1430 glOrtho (0, allocation
.width
, allocation
.height
, 0, 0, 100);
1431 glMatrixMode (GL_MODELVIEW
);
1433 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
1435 ghid_invalidate_current_gc ();
1437 /* Setup stenciling */
1438 glDisable (GL_STENCIL_TEST
);
1441 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
1442 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
1443 ((gport
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
1444 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
1446 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
1449 return &ghid_graphics
;
1453 ghid_flush_debug_draw (void)
1455 render_priv
*priv
= gport
->render_priv
;
1456 GtkWidget
*widget
= gport
->drawing_area
;
1457 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
1459 hidgl_flush_triangles (priv
->hidgl
);
1461 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
1462 gdk_gl_drawable_swap_buffers (pGlDrawable
);
1468 ghid_finish_debug_draw (void)
1470 render_priv
*priv
= gport
->render_priv
;
1472 hidgl_flush_triangles (priv
->hidgl
);
1475 ghid_end_drawing (gport
, gport
->drawing_area
);
1479 determinant_2x2 (float m
[2][2])
1482 det
= m
[0][0] * m
[1][1] -
1489 determinant_4x4 (float m
[4][4])
1492 det
= m
[0][3] * m
[1][2] * m
[2][1] * m
[3][0]-m
[0][2] * m
[1][3] * m
[2][1] * m
[3][0] -
1493 m
[0][3] * m
[1][1] * m
[2][2] * m
[3][0]+m
[0][1] * m
[1][3] * m
[2][2] * m
[3][0] +
1494 m
[0][2] * m
[1][1] * m
[2][3] * m
[3][0]-m
[0][1] * m
[1][2] * m
[2][3] * m
[3][0] -
1495 m
[0][3] * m
[1][2] * m
[2][0] * m
[3][1]+m
[0][2] * m
[1][3] * m
[2][0] * m
[3][1] +
1496 m
[0][3] * m
[1][0] * m
[2][2] * m
[3][1]-m
[0][0] * m
[1][3] * m
[2][2] * m
[3][1] -
1497 m
[0][2] * m
[1][0] * m
[2][3] * m
[3][1]+m
[0][0] * m
[1][2] * m
[2][3] * m
[3][1] +
1498 m
[0][3] * m
[1][1] * m
[2][0] * m
[3][2]-m
[0][1] * m
[1][3] * m
[2][0] * m
[3][2] -
1499 m
[0][3] * m
[1][0] * m
[2][1] * m
[3][2]+m
[0][0] * m
[1][3] * m
[2][1] * m
[3][2] +
1500 m
[0][1] * m
[1][0] * m
[2][3] * m
[3][2]-m
[0][0] * m
[1][1] * m
[2][3] * m
[3][2] -
1501 m
[0][2] * m
[1][1] * m
[2][0] * m
[3][3]+m
[0][1] * m
[1][2] * m
[2][0] * m
[3][3] +
1502 m
[0][2] * m
[1][0] * m
[2][1] * m
[3][3]-m
[0][0] * m
[1][2] * m
[2][1] * m
[3][3] -
1503 m
[0][1] * m
[1][0] * m
[2][2] * m
[3][3]+m
[0][0] * m
[1][1] * m
[2][2] * m
[3][3];
1509 invert_2x2 (float m
[2][2], float out
[2][2])
1511 float scale
= 1 / determinant_2x2 (m
);
1512 out
[0][0] = m
[1][1] * scale
;
1513 out
[0][1] = -m
[0][1] * scale
;
1514 out
[1][0] = -m
[1][0] * scale
;
1515 out
[1][1] = m
[0][0] * scale
;
1520 invert_4x4 (float m
[4][4], float out
[4][4])
1522 float scale
= 1 / determinant_4x4 (m
);
1524 out
[0][0] = (m
[1][2] * m
[2][3] * m
[3][1] - m
[1][3] * m
[2][2] * m
[3][1] +
1525 m
[1][3] * m
[2][1] * m
[3][2] - m
[1][1] * m
[2][3] * m
[3][2] -
1526 m
[1][2] * m
[2][1] * m
[3][3] + m
[1][1] * m
[2][2] * m
[3][3]) * scale
;
1527 out
[0][1] = (m
[0][3] * m
[2][2] * m
[3][1] - m
[0][2] * m
[2][3] * m
[3][1] -
1528 m
[0][3] * m
[2][1] * m
[3][2] + m
[0][1] * m
[2][3] * m
[3][2] +
1529 m
[0][2] * m
[2][1] * m
[3][3] - m
[0][1] * m
[2][2] * m
[3][3]) * scale
;
1530 out
[0][2] = (m
[0][2] * m
[1][3] * m
[3][1] - m
[0][3] * m
[1][2] * m
[3][1] +
1531 m
[0][3] * m
[1][1] * m
[3][2] - m
[0][1] * m
[1][3] * m
[3][2] -
1532 m
[0][2] * m
[1][1] * m
[3][3] + m
[0][1] * m
[1][2] * m
[3][3]) * scale
;
1533 out
[0][3] = (m
[0][3] * m
[1][2] * m
[2][1] - m
[0][2] * m
[1][3] * m
[2][1] -
1534 m
[0][3] * m
[1][1] * m
[2][2] + m
[0][1] * m
[1][3] * m
[2][2] +
1535 m
[0][2] * m
[1][1] * m
[2][3] - m
[0][1] * m
[1][2] * m
[2][3]) * scale
;
1536 out
[1][0] = (m
[1][3] * m
[2][2] * m
[3][0] - m
[1][2] * m
[2][3] * m
[3][0] -
1537 m
[1][3] * m
[2][0] * m
[3][2] + m
[1][0] * m
[2][3] * m
[3][2] +
1538 m
[1][2] * m
[2][0] * m
[3][3] - m
[1][0] * m
[2][2] * m
[3][3]) * scale
;
1539 out
[1][1] = (m
[0][2] * m
[2][3] * m
[3][0] - m
[0][3] * m
[2][2] * m
[3][0] +
1540 m
[0][3] * m
[2][0] * m
[3][2] - m
[0][0] * m
[2][3] * m
[3][2] -
1541 m
[0][2] * m
[2][0] * m
[3][3] + m
[0][0] * m
[2][2] * m
[3][3]) * scale
;
1542 out
[1][2] = (m
[0][3] * m
[1][2] * m
[3][0] - m
[0][2] * m
[1][3] * m
[3][0] -
1543 m
[0][3] * m
[1][0] * m
[3][2] + m
[0][0] * m
[1][3] * m
[3][2] +
1544 m
[0][2] * m
[1][0] * m
[3][3] - m
[0][0] * m
[1][2] * m
[3][3]) * scale
;
1545 out
[1][3] = (m
[0][2] * m
[1][3] * m
[2][0] - m
[0][3] * m
[1][2] * m
[2][0] +
1546 m
[0][3] * m
[1][0] * m
[2][2] - m
[0][0] * m
[1][3] * m
[2][2] -
1547 m
[0][2] * m
[1][0] * m
[2][3] + m
[0][0] * m
[1][2] * m
[2][3]) * scale
;
1548 out
[2][0] = (m
[1][1] * m
[2][3] * m
[3][0] - m
[1][3] * m
[2][1] * m
[3][0] +
1549 m
[1][3] * m
[2][0] * m
[3][1] - m
[1][0] * m
[2][3] * m
[3][1] -
1550 m
[1][1] * m
[2][0] * m
[3][3] + m
[1][0] * m
[2][1] * m
[3][3]) * scale
;
1551 out
[2][1] = (m
[0][3] * m
[2][1] * m
[3][0] - m
[0][1] * m
[2][3] * m
[3][0] -
1552 m
[0][3] * m
[2][0] * m
[3][1] + m
[0][0] * m
[2][3] * m
[3][1] +
1553 m
[0][1] * m
[2][0] * m
[3][3] - m
[0][0] * m
[2][1] * m
[3][3]) * scale
;
1554 out
[2][2] = (m
[0][1] * m
[1][3] * m
[3][0] - m
[0][3] * m
[1][1] * m
[3][0] +
1555 m
[0][3] * m
[1][0] * m
[3][1] - m
[0][0] * m
[1][3] * m
[3][1] -
1556 m
[0][1] * m
[1][0] * m
[3][3] + m
[0][0] * m
[1][1] * m
[3][3]) * scale
;
1557 out
[2][3] = (m
[0][3] * m
[1][1] * m
[2][0] - m
[0][1] * m
[1][3] * m
[2][0] -
1558 m
[0][3] * m
[1][0] * m
[2][1] + m
[0][0] * m
[1][3] * m
[2][1] +
1559 m
[0][1] * m
[1][0] * m
[2][3] - m
[0][0] * m
[1][1] * m
[2][3]) * scale
;
1560 out
[3][0] = (m
[1][2] * m
[2][1] * m
[3][0] - m
[1][1] * m
[2][2] * m
[3][0] -
1561 m
[1][2] * m
[2][0] * m
[3][1] + m
[1][0] * m
[2][2] * m
[3][1] +
1562 m
[1][1] * m
[2][0] * m
[3][2] - m
[1][0] * m
[2][1] * m
[3][2]) * scale
;
1563 out
[3][1] = (m
[0][1] * m
[2][2] * m
[3][0] - m
[0][2] * m
[2][1] * m
[3][0] +
1564 m
[0][2] * m
[2][0] * m
[3][1] - m
[0][0] * m
[2][2] * m
[3][1] -
1565 m
[0][1] * m
[2][0] * m
[3][2] + m
[0][0] * m
[2][1] * m
[3][2]) * scale
;
1566 out
[3][2] = (m
[0][2] * m
[1][1] * m
[3][0] - m
[0][1] * m
[1][2] * m
[3][0] -
1567 m
[0][2] * m
[1][0] * m
[3][1] + m
[0][0] * m
[1][2] * m
[3][1] +
1568 m
[0][1] * m
[1][0] * m
[3][2] - m
[0][0] * m
[1][1] * m
[3][2]) * scale
;
1569 out
[3][3] = (m
[0][1] * m
[1][2] * m
[2][0] - m
[0][2] * m
[1][1] * m
[2][0] +
1570 m
[0][2] * m
[1][0] * m
[2][1] - m
[0][0] * m
[1][2] * m
[2][1] -
1571 m
[0][1] * m
[1][0] * m
[2][2] + m
[0][0] * m
[1][1] * m
[2][2]) * scale
;
1577 ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
)
1580 float inv_mat
[2][2];
1584 ex = view_matrix[0][0] * vx +
1585 view_matrix[0][1] * vy +
1586 view_matrix[0][2] * vz +
1587 view_matrix[0][3] * 1;
1588 ey = view_matrix[1][0] * vx +
1589 view_matrix[1][1] * vy +
1590 view_matrix[1][2] * vz +
1591 view_matrix[1][3] * 1;
1592 UNKNOWN ez = view_matrix[2][0] * vx +
1593 view_matrix[2][1] * vy +
1594 view_matrix[2][2] * vz +
1595 view_matrix[2][3] * 1;
1597 ex - view_matrix[0][3] * 1
1598 - view_matrix[0][2] * vz
1599 = view_matrix[0][0] * vx +
1600 view_matrix[0][1] * vy;
1602 ey - view_matrix[1][3] * 1
1603 - view_matrix[1][2] * vz
1604 = view_matrix[1][0] * vx +
1605 view_matrix[1][1] * vy;
1608 /* NB: last_modelview_matrix is transposed in memory! */
1609 x
= (float)ex
- last_modelview_matrix
[3][0] * 1
1610 - last_modelview_matrix
[2][0] * pcb_z
;
1612 y
= (float)ey
- last_modelview_matrix
[3][1] * 1
1613 - last_modelview_matrix
[2][1] * pcb_z
;
1616 x = view_matrix[0][0] * vx +
1617 view_matrix[0][1] * vy;
1619 y = view_matrix[1][0] * vx +
1620 view_matrix[1][1] * vy;
1622 [view_matrix[0][0] view_matrix[0][1]] [vx] = [x]
1623 [view_matrix[1][0] view_matrix[1][1]] [vy] [y]
1626 mat
[0][0] = last_modelview_matrix
[0][0];
1627 mat
[0][1] = last_modelview_matrix
[1][0];
1628 mat
[1][0] = last_modelview_matrix
[0][1];
1629 mat
[1][1] = last_modelview_matrix
[1][1];
1631 /* if (determinant_2x2 (mat) < 0.00001) */
1632 /* printf ("Determinant is quite small\n"); */
1634 invert_2x2 (mat
, inv_mat
);
1636 *pcb_x
= (int)(inv_mat
[0][0] * x
+ inv_mat
[0][1] * y
);
1637 *pcb_y
= (int)(inv_mat
[1][0] * x
+ inv_mat
[1][1] * y
);
1642 ghid_event_to_pcb_coords (int event_x
, int event_y
, Coord
*pcb_x
, Coord
*pcb_y
)
1644 ghid_unproject_to_z_plane (event_x
, event_y
, global_depth
, pcb_x
, pcb_y
);
1650 ghid_pcb_to_event_coords (Coord pcb_x
, Coord pcb_y
, int *event_x
, int *event_y
)
1652 /* NB: last_modelview_matrix is transposed in memory */
1653 float w
= last_modelview_matrix
[0][3] * (float)pcb_x
+
1654 last_modelview_matrix
[1][3] * (float)pcb_y
+
1655 last_modelview_matrix
[2][3] * 0. +
1656 last_modelview_matrix
[3][3] * 1.;
1658 *event_x
= (last_modelview_matrix
[0][0] * (float)pcb_x
+
1659 last_modelview_matrix
[1][0] * (float)pcb_y
+
1660 last_modelview_matrix
[2][0] * global_depth
+
1661 last_modelview_matrix
[3][0] * 1.) / w
;
1662 *event_y
= (last_modelview_matrix
[0][1] * (float)pcb_x
+
1663 last_modelview_matrix
[1][1] * (float)pcb_y
+
1664 last_modelview_matrix
[2][1] * global_depth
+
1665 last_modelview_matrix
[3][1] * 1.) / w
;
1671 ghid_view_2d (void *ball
, gboolean view_2d
, gpointer userdata
)
1673 global_view_2d
= view_2d
;
1674 ghid_invalidate_all ();
1678 ghid_port_rotate (void *ball
, float *quarternion
, gpointer userdata
)
1684 build_rotmatrix (view_matrix
, quarternion
);
1687 for (row
= 0; row
< 4; row
++) {
1688 printf ("[ %f", view_matrix
[row
][0]);
1689 for (column
= 1; column
< 4; column
++) {
1690 printf (",\t%f", view_matrix
[row
][column
]);
1697 ghid_invalidate_all ();
1701 #define LEAD_USER_WIDTH 0.2 /* millimeters */
1702 #define LEAD_USER_PERIOD (1000 / 20) /* 20fps (in ms) */
1703 #define LEAD_USER_VELOCITY 3. /* millimeters per second */
1704 #define LEAD_USER_ARC_COUNT 3
1705 #define LEAD_USER_ARC_SEPARATION 3. /* millimeters */
1706 #define LEAD_USER_INITIAL_RADIUS 10. /* millimetres */
1707 #define LEAD_USER_COLOR_R 1.
1708 #define LEAD_USER_COLOR_G 1.
1709 #define LEAD_USER_COLOR_B 0.
1712 draw_lead_user (hidGC gc
, render_priv
*priv
)
1714 gtkGC gtk_gc
= (gtkGC
)gc
;
1716 double radius
= priv
->lead_user_radius
;
1717 double width
= MM_TO_COORD (LEAD_USER_WIDTH
);
1718 double separation
= MM_TO_COORD (LEAD_USER_ARC_SEPARATION
);
1720 if (!priv
->lead_user
)
1723 glPushAttrib (GL_CURRENT_BIT
| GL_COLOR_BUFFER_BIT
);
1724 glEnable (GL_COLOR_LOGIC_OP
);
1726 glColor3f (LEAD_USER_COLOR_R
, LEAD_USER_COLOR_G
,LEAD_USER_COLOR_B
);
1729 /* arcs at the approrpriate radii */
1731 for (i
= 0; i
< LEAD_USER_ARC_COUNT
; i
++, radius
-= separation
)
1734 radius
+= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1736 /* Draw an arc at radius */
1737 hidgl_draw_arc (gc
, width
, priv
->lead_user_x
, priv
->lead_user_y
,
1738 radius
, radius
, 0, 360, gport
->view
.coord_per_px
);
1741 hidgl_flush_triangles (gtk_gc
->hidgl_gc
.hidgl
);
1746 lead_user_cb (gpointer data
)
1748 render_priv
*priv
= data
;
1750 double elapsed_time
;
1752 /* Queue a redraw */
1753 ghid_invalidate_all ();
1756 elapsed_time
= g_timer_elapsed (priv
->lead_user_timer
, NULL
);
1757 g_timer_start (priv
->lead_user_timer
);
1759 step
= MM_TO_COORD (LEAD_USER_VELOCITY
* elapsed_time
);
1760 if (priv
->lead_user_radius
> step
)
1761 priv
->lead_user_radius
-= step
;
1763 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1769 ghid_lead_user_to_location (Coord x
, Coord y
)
1771 render_priv
*priv
= gport
->render_priv
;
1773 ghid_cancel_lead_user ();
1775 priv
->lead_user
= true;
1776 priv
->lead_user_x
= x
;
1777 priv
->lead_user_y
= y
;
1778 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
1779 priv
->lead_user_timeout
= g_timeout_add (LEAD_USER_PERIOD
, lead_user_cb
, priv
);
1780 priv
->lead_user_timer
= g_timer_new ();
1784 ghid_cancel_lead_user (void)
1786 render_priv
*priv
= gport
->render_priv
;
1788 if (priv
->lead_user_timeout
)
1789 g_source_remove (priv
->lead_user_timeout
);
1791 if (priv
->lead_user_timer
)
1792 g_timer_destroy (priv
->lead_user_timer
);
1794 if (priv
->lead_user
)
1795 ghid_invalidate_all ();
1797 priv
->lead_user_timeout
= 0;
1798 priv
->lead_user_timer
= NULL
;
1799 priv
->lead_user
= false;