4 * PCB, interactive printed circuit board design
5 * Copyright (C) 2009-2011 PCB Contributers (See ChangeLog for details)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 /* The Linux OpenGL ABI 1.0 spec requires that we define
36 * GL_GLEXT_PROTOTYPES before including gl.h or glx.h for extensions
37 * in order to get prototypes:
38 * http://www.opengl.org/registry/ABI/
40 #define GL_GLEXT_PROTOTYPES 1
41 #ifdef HAVE_OPENGL_GL_H
42 # include <OpenGL/gl.h>
47 #ifdef HAVE_OPENGL_GLU_H
48 # include <OpenGL/glu.h>
54 #include "crosshair.h"
65 #ifdef HAVE_LIBDMALLOC
70 triangle_buffer buffer
;
71 float global_depth
= 0;
74 hidgl_init_triangle_array (triangle_buffer
*buffer
)
76 buffer
->triangle_count
= 0;
77 buffer
->coord_comp_count
= 0;
81 hidgl_flush_triangles (triangle_buffer
*buffer
)
83 if (buffer
->triangle_count
== 0)
86 glEnableClientState (GL_VERTEX_ARRAY
);
87 glVertexPointer (3, GL_FLOAT
, 0, buffer
->triangle_array
);
88 glDrawArrays (GL_TRIANGLES
, 0, buffer
->triangle_count
* 3);
89 glDisableClientState (GL_VERTEX_ARRAY
);
91 buffer
->triangle_count
= 0;
92 buffer
->coord_comp_count
= 0;
96 hidgl_ensure_triangle_space (triangle_buffer
*buffer
, int count
)
98 if (count
> TRIANGLE_ARRAY_SIZE
)
100 fprintf (stderr
, "Not enough space in vertex buffer\n");
101 fprintf (stderr
, "Requested %i triangles, %i available\n",
102 count
, TRIANGLE_ARRAY_SIZE
);
105 if (count
> TRIANGLE_ARRAY_SIZE
- buffer
->triangle_count
)
106 hidgl_flush_triangles (buffer
);
110 hidgl_set_depth (float depth
)
112 global_depth
= depth
;
116 hidgl_draw_grid (BoxType
*drawn_area
)
118 static GLfloat
*points
= 0;
119 static int npoints
= 0;
120 Coord x1
, y1
, x2
, y2
, n
, i
;
123 if (!Settings
.DrawGrid
)
126 x1
= GridFit (MAX (0, drawn_area
->X1
), PCB
->Grid
, PCB
->GridOffsetX
);
127 y1
= GridFit (MAX (0, drawn_area
->Y1
), PCB
->Grid
, PCB
->GridOffsetY
);
128 x2
= GridFit (MIN (PCB
->MaxWidth
, drawn_area
->X2
), PCB
->Grid
, PCB
->GridOffsetX
);
129 y2
= GridFit (MIN (PCB
->MaxHeight
, drawn_area
->Y2
), PCB
->Grid
, PCB
->GridOffsetY
);
145 n
= (int) ((x2
- x1
) / PCB
->Grid
+ 0.5) + 1;
149 points
= realloc (points
, npoints
* 3 * sizeof (GLfloat
));
152 glEnableClientState (GL_VERTEX_ARRAY
);
153 glVertexPointer (3, GL_FLOAT
, 0, points
);
156 for (x
= x1
; x
<= x2
; x
+= PCB
->Grid
)
158 points
[3 * n
+ 0] = x
;
159 points
[3 * n
+ 2] = global_depth
;
162 for (y
= y1
; y
<= y2
; y
+= PCB
->Grid
)
164 for (i
= 0; i
< n
; i
++)
165 points
[3 * i
+ 1] = y
;
166 glDrawArrays (GL_POINTS
, 0, n
);
169 glDisableClientState (GL_VERTEX_ARRAY
);
172 #define MAX_PIXELS_ARC_TO_CHORD 0.5
174 int calc_slices (float pix_radius
, float sweep_angle
)
178 if (pix_radius
<= MAX_PIXELS_ARC_TO_CHORD
)
181 slices
= sweep_angle
/ acosf (1 - MAX_PIXELS_ARC_TO_CHORD
/ pix_radius
) / 2.;
182 return (int)ceilf (slices
);
185 #define MIN_TRIANGLES_PER_CAP 3
186 #define MAX_TRIANGLES_PER_CAP 90
187 static void draw_cap (Coord width
, Coord x
, Coord y
, Angle angle
, double scale
)
189 float last_capx
, last_capy
;
191 float radius
= width
/ 2.;
192 int slices
= calc_slices (radius
/ scale
, M_PI
);
195 if (slices
< MIN_TRIANGLES_PER_CAP
)
196 slices
= MIN_TRIANGLES_PER_CAP
;
198 if (slices
> MAX_TRIANGLES_PER_CAP
)
199 slices
= MAX_TRIANGLES_PER_CAP
;
201 hidgl_ensure_triangle_space (&buffer
, slices
);
203 last_capx
= radius
* cosf (angle
* M_PI
/ 180.) + x
;
204 last_capy
= -radius
* sinf (angle
* M_PI
/ 180.) + y
;
205 for (i
= 0; i
< slices
; i
++) {
206 capx
= radius
* cosf (angle
* M_PI
/ 180. + ((float)(i
+ 1)) * M_PI
/ (float)slices
) + x
;
207 capy
= -radius
* sinf (angle
* M_PI
/ 180. + ((float)(i
+ 1)) * M_PI
/ (float)slices
) + y
;
208 hidgl_add_triangle (&buffer
, last_capx
, last_capy
, capx
, capy
, x
, y
);
215 hidgl_draw_line (int cap
, Coord width
, Coord x1
, Coord y1
, Coord x2
, Coord y2
, double scale
)
218 double deltax
, deltay
, length
;
220 int circular_caps
= 0;
232 length
= sqrt (deltax
* deltax
+ deltay
* deltay
);
235 /* Assume the orientation of the line is horizontal */
242 wdy
= deltax
* width
/ 2. / length
;
243 wdx
= -deltay
* width
/ 2. / length
;
246 angle
= -180. / M_PI
* atan2 (deltay
, deltax
);
256 x1
-= deltax
* width
/ 2. / length
;
257 y1
-= deltay
* width
/ 2. / length
;
258 x2
+= deltax
* width
/ 2. / length
;
259 y2
+= deltay
* width
/ 2. / length
;
263 hidgl_ensure_triangle_space (&buffer
, 2);
264 hidgl_add_triangle (&buffer
, x1
- wdx
, y1
- wdy
,
267 hidgl_add_triangle (&buffer
, x1
- wdx
, y1
- wdy
,
271 /* Don't bother capping hairlines */
272 if (circular_caps
&& !hairline
)
274 draw_cap (width
, x1
, y1
, angle
+ 90., scale
);
275 draw_cap (width
, x2
, y2
, angle
- 90., scale
);
279 #define MIN_SLICES_PER_ARC 6
280 #define MAX_SLICES_PER_ARC 360
282 hidgl_draw_arc (Coord width
, Coord x
, Coord y
, Coord rx
, Coord ry
,
283 Angle start_angle
, Angle delta_angle
, double scale
)
285 float last_inner_x
, last_inner_y
;
286 float last_outer_x
, last_outer_y
;
287 float inner_x
, inner_y
;
288 float outer_x
, outer_y
;
291 float cos_ang
, sin_ang
;
292 float start_angle_rad
;
293 float delta_angle_rad
;
294 float angle_incr_rad
;
305 inner_r
= rx
- width
/ 2.;
306 outer_r
= rx
+ width
/ 2.;
308 if (delta_angle
< 0) {
309 start_angle
+= delta_angle
;
310 delta_angle
= - delta_angle
;
313 start_angle_rad
= start_angle
* M_PI
/ 180.;
314 delta_angle_rad
= delta_angle
* M_PI
/ 180.;
316 slices
= calc_slices ((rx
+ width
/ 2.) / scale
, delta_angle_rad
);
318 if (slices
< MIN_SLICES_PER_ARC
)
319 slices
= MIN_SLICES_PER_ARC
;
321 if (slices
> MAX_SLICES_PER_ARC
)
322 slices
= MAX_SLICES_PER_ARC
;
324 hidgl_ensure_triangle_space (&buffer
, 2 * slices
);
326 angle_incr_rad
= delta_angle_rad
/ (float)slices
;
328 cos_ang
= cosf (start_angle_rad
);
329 sin_ang
= sinf (start_angle_rad
);
330 last_inner_x
= -inner_r
* cos_ang
+ x
; last_inner_y
= inner_r
* sin_ang
+ y
;
331 last_outer_x
= -outer_r
* cos_ang
+ x
; last_outer_y
= outer_r
* sin_ang
+ y
;
332 for (i
= 1; i
<= slices
; i
++) {
333 cos_ang
= cosf (start_angle_rad
+ ((float)(i
)) * angle_incr_rad
);
334 sin_ang
= sinf (start_angle_rad
+ ((float)(i
)) * angle_incr_rad
);
335 inner_x
= -inner_r
* cos_ang
+ x
; inner_y
= inner_r
* sin_ang
+ y
;
336 outer_x
= -outer_r
* cos_ang
+ x
; outer_y
= outer_r
* sin_ang
+ y
;
337 hidgl_add_triangle (&buffer
, last_inner_x
, last_inner_y
,
338 last_outer_x
, last_outer_y
,
340 hidgl_add_triangle (&buffer
, last_inner_x
, last_inner_y
,
343 last_inner_x
= inner_x
; last_inner_y
= inner_y
;
344 last_outer_x
= outer_x
; last_outer_y
= outer_y
;
347 /* Don't bother capping hairlines */
351 draw_cap (width
, x
+ rx
* -cosf (start_angle_rad
),
352 y
+ rx
* sinf (start_angle_rad
),
354 draw_cap (width
, x
+ rx
* -cosf (start_angle_rad
+ delta_angle_rad
),
355 y
+ rx
* sinf (start_angle_rad
+ delta_angle_rad
),
356 start_angle
+ delta_angle
+ 180., scale
);
360 hidgl_draw_rect (Coord x1
, Coord y1
, Coord x2
, Coord y2
)
362 glBegin (GL_LINE_LOOP
);
363 glVertex3f (x1
, y1
, global_depth
);
364 glVertex3f (x1
, y2
, global_depth
);
365 glVertex3f (x2
, y2
, global_depth
);
366 glVertex3f (x2
, y1
, global_depth
);
372 hidgl_fill_circle (Coord vx
, Coord vy
, Coord vr
, double scale
)
374 #define MIN_TRIANGLES_PER_CIRCLE 6
375 #define MAX_TRIANGLES_PER_CIRCLE 360
376 float last_x
, last_y
;
381 slices
= calc_slices (vr
/ scale
, 2 * M_PI
);
383 if (slices
< MIN_TRIANGLES_PER_CIRCLE
)
384 slices
= MIN_TRIANGLES_PER_CIRCLE
;
386 if (slices
> MAX_TRIANGLES_PER_CIRCLE
)
387 slices
= MAX_TRIANGLES_PER_CIRCLE
;
389 hidgl_ensure_triangle_space (&buffer
, slices
);
394 for (i
= 0; i
< slices
; i
++) {
396 x
= radius
* cosf (((float)(i
+ 1)) * 2. * M_PI
/ (float)slices
) + vx
;
397 y
= radius
* sinf (((float)(i
+ 1)) * 2. * M_PI
/ (float)slices
) + vy
;
398 hidgl_add_triangle (&buffer
, vx
, vy
, last_x
, last_y
, x
, y
);
404 #define MAX_COMBINED_MALLOCS 2500
405 static void *combined_to_free
[MAX_COMBINED_MALLOCS
];
406 static int combined_num_to_free
= 0;
408 static GLenum tessVertexType
;
409 static int stashed_vertices
;
410 static int triangle_comp_idx
;
414 myError (GLenum errno
)
416 printf ("gluTess error: %s\n", gluErrorString (errno
));
422 while (combined_num_to_free
)
423 free (combined_to_free
[-- combined_num_to_free
]);
427 myCombine ( GLdouble coords
[3], void *vertex_data
[4], GLfloat weight
[4], void **dataOut
)
429 #define MAX_COMBINED_VERTICES 2500
430 static GLdouble combined_vertices
[3 * MAX_COMBINED_VERTICES
];
431 static int num_combined_vertices
= 0;
433 GLdouble
*new_vertex
;
435 if (num_combined_vertices
< MAX_COMBINED_VERTICES
)
437 new_vertex
= &combined_vertices
[3 * num_combined_vertices
];
438 num_combined_vertices
++;
442 new_vertex
= malloc (3 * sizeof (GLdouble
));
444 if (combined_num_to_free
< MAX_COMBINED_MALLOCS
)
445 combined_to_free
[combined_num_to_free
++] = new_vertex
;
447 printf ("myCombine leaking %lu bytes of memory\n", 3 * sizeof (GLdouble
));
450 new_vertex
[0] = coords
[0];
451 new_vertex
[1] = coords
[1];
452 new_vertex
[2] = coords
[2];
454 *dataOut
= new_vertex
;
458 myBegin (GLenum type
)
460 tessVertexType
= type
;
461 stashed_vertices
= 0;
462 triangle_comp_idx
= 0;
465 static double global_scale
;
468 myVertex (GLdouble
*vertex_data
)
470 static GLfloat triangle_vertices
[2 * 3];
472 if (tessVertexType
== GL_TRIANGLE_STRIP
||
473 tessVertexType
== GL_TRIANGLE_FAN
)
475 if (stashed_vertices
< 2)
477 triangle_vertices
[triangle_comp_idx
++] = vertex_data
[0];
478 triangle_vertices
[triangle_comp_idx
++] = vertex_data
[1];
483 hidgl_ensure_triangle_space (&buffer
, 1);
484 hidgl_add_triangle (&buffer
,
485 triangle_vertices
[0], triangle_vertices
[1],
486 triangle_vertices
[2], triangle_vertices
[3],
487 vertex_data
[0], vertex_data
[1]);
489 if (tessVertexType
== GL_TRIANGLE_STRIP
)
491 /* STRIP saves the last two vertices for re-use in the next triangle */
492 triangle_vertices
[0] = triangle_vertices
[2];
493 triangle_vertices
[1] = triangle_vertices
[3];
495 /* Both FAN and STRIP save the last vertex for re-use in the next triangle */
496 triangle_vertices
[2] = vertex_data
[0];
497 triangle_vertices
[3] = vertex_data
[1];
500 else if (tessVertexType
== GL_TRIANGLES
)
502 triangle_vertices
[triangle_comp_idx
++] = vertex_data
[0];
503 triangle_vertices
[triangle_comp_idx
++] = vertex_data
[1];
505 if (stashed_vertices
== 3)
507 hidgl_ensure_triangle_space (&buffer
, 1);
508 hidgl_add_triangle (&buffer
,
509 triangle_vertices
[0], triangle_vertices
[1],
510 triangle_vertices
[2], triangle_vertices
[3],
511 triangle_vertices
[4], triangle_vertices
[5]);
512 triangle_comp_idx
= 0;
513 stashed_vertices
= 0;
517 printf ("Vertex received with unknown type\n");
521 hidgl_fill_polygon (int n_coords
, Coord
*x
, Coord
*y
)
527 assert (n_coords
> 0);
529 vertices
= malloc (sizeof(GLdouble
) * n_coords
* 3);
531 tobj
= gluNewTess ();
532 gluTessCallback(tobj
, GLU_TESS_BEGIN
, (_GLUfuncptr
)myBegin
);
533 gluTessCallback(tobj
, GLU_TESS_VERTEX
, (_GLUfuncptr
)myVertex
);
534 gluTessCallback(tobj
, GLU_TESS_COMBINE
, (_GLUfuncptr
)myCombine
);
535 gluTessCallback(tobj
, GLU_TESS_ERROR
, (_GLUfuncptr
)myError
);
537 gluTessBeginPolygon (tobj
, NULL
);
538 gluTessBeginContour (tobj
);
540 for (i
= 0; i
< n_coords
; i
++)
542 vertices
[0 + i
* 3] = x
[i
];
543 vertices
[1 + i
* 3] = y
[i
];
544 vertices
[2 + i
* 3] = 0.;
545 gluTessVertex (tobj
, &vertices
[i
* 3], &vertices
[i
* 3]);
548 gluTessEndContour (tobj
);
549 gluTessEndPolygon (tobj
);
550 gluDeleteTess (tobj
);
557 tesselate_contour (GLUtesselator
*tobj
, PLINE
*contour
, GLdouble
*vertices
,
560 VNODE
*vn
= &contour
->head
;
563 /* If the contour is round, and hidgl_fill_circle would use
564 * less slices than we have vertices to draw it, then call
565 * hidgl_fill_circle to draw this contour.
567 if (contour
->is_round
) {
568 double slices
= calc_slices (contour
->radius
/ scale
, 2 * M_PI
);
569 if (slices
< contour
->Count
) {
570 hidgl_fill_circle (contour
->cx
, contour
->cy
, contour
->radius
, scale
);
575 gluTessBeginPolygon (tobj
, NULL
);
576 gluTessBeginContour (tobj
);
578 vertices
[0 + offset
] = vn
->point
[0];
579 vertices
[1 + offset
] = vn
->point
[1];
580 vertices
[2 + offset
] = 0.;
581 gluTessVertex (tobj
, &vertices
[offset
], &vertices
[offset
]);
583 } while ((vn
= vn
->next
) != &contour
->head
);
584 gluTessEndContour (tobj
);
585 gluTessEndPolygon (tobj
);
588 struct do_hole_info
{
595 do_hole (const BoxType
*b
, void *cl
)
597 struct do_hole_info
*info
= cl
;
598 PLINE
*curc
= (PLINE
*) b
;
600 /* Ignore the outer contour - we draw it first explicitly*/
601 if (curc
->Flags
.orient
== PLF_DIR
) {
605 tesselate_contour (info
->tobj
, curc
, info
->vertices
, info
->scale
);
609 static GLint stencil_bits
;
610 static int dirty_bits
= 0;
611 static int assigned_bits
= 0;
613 /* FIXME: JUST DRAWS THE FIRST PIECE.. TODO: SUPPORT FOR FULLPOLY POLYGONS */
615 hidgl_fill_pcb_polygon (PolygonType
*poly
, const BoxType
*clip_box
, double scale
)
617 int vertex_count
= 0;
619 struct do_hole_info info
;
623 global_scale
= scale
;
625 if (poly
->Clipped
== NULL
)
627 fprintf (stderr
, "hidgl_fill_pcb_polygon: poly->Clipped == NULL\n");
631 stencil_bit
= hidgl_assign_clear_stencil_bit ();
634 printf ("hidgl_fill_pcb_polygon: No free stencil bits, aborting polygon\n");
638 /* Flush out any existing geoemtry to be rendered */
639 hidgl_flush_triangles (&buffer
);
641 /* Walk the polygon structure, counting vertices */
642 /* This gives an upper bound on the amount of storage required */
643 for (contour
= poly
->Clipped
->contours
;
644 contour
!= NULL
; contour
= contour
->next
)
645 vertex_count
= MAX (vertex_count
, contour
->Count
);
647 info
.vertices
= malloc (sizeof(GLdouble
) * vertex_count
* 3);
648 info
.tobj
= gluNewTess ();
649 gluTessCallback(info
.tobj
, GLU_TESS_BEGIN
, (_GLUfuncptr
)myBegin
);
650 gluTessCallback(info
.tobj
, GLU_TESS_VERTEX
, (_GLUfuncptr
)myVertex
);
651 gluTessCallback(info
.tobj
, GLU_TESS_COMBINE
, (_GLUfuncptr
)myCombine
);
652 gluTessCallback(info
.tobj
, GLU_TESS_ERROR
, (_GLUfuncptr
)myError
);
654 glPushAttrib (GL_STENCIL_BUFFER_BIT
); /* Save the write mask etc.. for final restore */
655 glEnable (GL_STENCIL_TEST
);
656 glPushAttrib (GL_STENCIL_BUFFER_BIT
| /* Resave the stencil write-mask etc.., and */
657 GL_COLOR_BUFFER_BIT
); /* the colour buffer write mask etc.. for part way restore */
658 glStencilMask (stencil_bit
); /* Only write to our stencil bit */
659 glStencilFunc (GL_ALWAYS
, stencil_bit
, stencil_bit
); /* Always pass stencil test, ref value is our bit */
660 glColorMask (0, 0, 0, 0); /* Disable writting in color buffer */
662 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value */
664 /* Drawing operations now set our reference bit in the stencil buffer */
666 r_search (poly
->Clipped
->contour_tree
, clip_box
, NULL
, do_hole
, &info
);
667 hidgl_flush_triangles (&buffer
);
669 glPopAttrib (); /* Restore the colour and stencil buffer write-mask etc.. */
671 glStencilOp (GL_KEEP
, GL_KEEP
, GL_INVERT
); /* This allows us to toggle the bit on any subcompositing bitplane */
672 /* If the stencil test has passed, we know that bit is 0, so we're */
673 /* effectively just setting it to 1. */
675 glStencilFunc (GL_GEQUAL
, 0, assigned_bits
); /* Pass stencil test if all assigned bits clear, */
676 /* reference is all assigned bits so we set */
677 /* any bits permitted by the stencil writemask */
679 /* Drawing operations as masked to areas where the stencil buffer is '0' */
681 /* Draw the polygon outer */
682 tesselate_contour (info
.tobj
, poly
->Clipped
->contours
, info
.vertices
, scale
);
683 hidgl_flush_triangles (&buffer
);
685 /* Unassign our stencil buffer bit */
686 hidgl_return_stencil_bit (stencil_bit
);
688 glPopAttrib (); /* Restore the stencil buffer write-mask etc.. */
690 gluDeleteTess (info
.tobj
);
692 free (info
.vertices
);
696 hidgl_fill_rect (Coord x1
, Coord y1
, Coord x2
, Coord y2
)
698 hidgl_ensure_triangle_space (&buffer
, 2);
699 hidgl_add_triangle (&buffer
, x1
, y1
, x1
, y2
, x2
, y2
);
700 hidgl_add_triangle (&buffer
, x2
, y1
, x2
, y2
, x1
, y1
);
706 glGetIntegerv (GL_STENCIL_BITS
, &stencil_bits
);
708 if (stencil_bits
== 0)
710 printf ("No stencil bits available.\n"
711 "Cannot mask polygon holes or subcomposite layers\n");
712 /* TODO: Flag this to the HID so it can revert to the dicer? */
714 else if (stencil_bits
== 1)
716 printf ("Only one stencil bitplane avilable\n"
717 "Cannot use stencil buffer to sub-composite layers.\n");
718 /* Do we need to disable that somewhere? */
723 hidgl_start_render (void)
726 hidgl_init_triangle_array (&buffer
);
730 hidgl_finish_render (void)
735 hidgl_stencil_bits (void)
741 hidgl_clean_unassigned_stencil (void)
743 glPushAttrib (GL_STENCIL_BUFFER_BIT
);
744 glStencilMask (~assigned_bits
);
746 glClear (GL_STENCIL_BUFFER_BIT
);
751 hidgl_assign_clear_stencil_bit (void)
753 int stencil_bitmask
= (1 << stencil_bits
) - 1;
757 if (assigned_bits
== stencil_bitmask
)
759 printf ("No more stencil bits available, total of %i already assigned\n",
764 /* Look for a bitplane we don't have to clear */
765 for (test
= 1; test
& stencil_bitmask
; test
<<= 1)
767 if (!(test
& dirty_bits
))
769 assigned_bits
|= test
;
773 else if (!first_dirty
&& !(test
& assigned_bits
))
779 /* Didn't find any non dirty planes. Clear those dirty ones which aren't in use */
780 hidgl_clean_unassigned_stencil ();
781 assigned_bits
|= first_dirty
;
782 dirty_bits
= assigned_bits
;
788 hidgl_return_stencil_bit (int bit
)
790 assigned_bits
&= ~bit
;
794 hidgl_reset_stencil_usage (void)