1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
<html>
<body>
<h1> HID: rendering vs. composite layers </h1>
<p>
All rendering is driven by the core. The core understands the PCB stackup,
layers, layer groups, compositions within the layer groups, extra labels,
layer visibility, etc. The HID is a slave device that takes drawing
instructions and blindly executes them.
<p>
However, the HID has a chance to alter which layer groups are drawn, using
the <i>set_layer_group</i> hooks return value.
<H2> Bursts and layer groups </H2>
<p>
The rendering is done in bursts. A burst may redraw only a small window
of the screen. Each bursts draws multiple layer groups, in Z-order, from
bottom (furthest from the eye of the user) to up (closest to the eye of
the user). Each layer group is drawn on a transparent sketch canvas. In positive mode,
objects are drawn with multiple colors on each sketch canvas. In negative mode
pixels are erased from the sketch canvas, making the affected pixels transparent again. Drawing
on a layer group (either positively or negatively) should
<b>overwrite</b> pixels on the same layer group. In other words, there's
no translucency between two overlapping objects drawn on the same layer
group.
<p>
There is a so called <i>output</i> canvas, which shall be cleared to
the background color upon <i>render_burst</i> / <i>start</i>. The background
color shall be fetched from the config tree (appearance/color/background).
<p>
The following steps are taken by the core in a burst:
<ul>
<li> 1. call to the <i>render_burst</i> hook with <i>start</i>
<li> 2. <i>set_layer_group</i> is called for the next layer; depending on the return value, the core will skip to step 7.
<li> 3. <i>set_drawing_mode</i> is called with <i>reset</i> (also indicates start of a composite layer)
<li> 4. <i>set_drawing_mode</i> is called with <i>positive</i> or <i>negative</i> to set draw or erase
<li> 5. objects are drawn
<li> 6. if there are subsequent composite layers, the core will jump back to 4.
<li> 7. <i>set_drawing_mode</i> is called with <i>flush</i> (also indicates end of a composite layer)
<li> 8. if there are further groups, the core jumps back to step 3.
<li> 9. call to the <i>render_burst</i> hook with <i>end</i>
</ul>
<p>
When <i>set_drawing_mode</i> / <i>reset</i> is called, the HID needs to
create a new sketch canvas, all pixels initialized to transparent. The
core may switch between positive and negative draw any time. When
<i>set_drawing_mode</i> / <i>flush</i> is called, the current sketch
canvas needs to be blitted onto the output (in a HID-specific way) and
the sketch canvas can be destroyed. The output canvas shall be flushed to
the screen upon <i>render_burst</i> / <i>end</i>.
<p>
Optional optimization: the most common case is when only positively drawn
layers are used to draw the final output. Drawing on separate sketch canvases and
blitting them onto an output buffer is a waste in this setup. To give HIDs a
chance to avoid the extra copies, <i>set_drawing_mode</i> calls have an
argument called <i>direct</i>. When the <i>direct</i> is set, it is safe
to directly draw on the output canvas, without allocating a sketch canvas. The
core guarantees the followings:
<ul>
<li> all calls of <i>set_drawing_mode</i> within drawing a layer group will have the same <i>direct</i> argument
<li> if <i>direct</i> is set for a layer group, <i>set_drawing_mode</i> will not be called with <i>negative</i>
<li> only the first N consecutive layer groups can be <i>direct</i>; once a group is drawn with <i>direct</i> unset, all subsequent groups will be drawn with <i>direct</i> unset
</ul>
<p>
It is possible that the core would draw the whole board in <i>direct</i>
mode. It is safe to ignore the <i>direct</i> argument and always use the
more expensive, sketch-canvas+blitting method.
<H2> GCs </H2>
<p>
The API contains Graphic Context, or GC for short. A GC is a pen with
properties like color and tip shape. The core will initialize multiple
GCs for the drawing and will pass a GC pointer with each drawing command.
<p>
Note: this concept is orthogonal to the above canvas based drawing.
Regardless of which GC is used, the object being drawn always ends up
making modifications to the currently active (sketch) canvas.
<p>
A GC can be initialized only after <i>render_burst</i> / <i>start</i>
and all GCs will be uninitialized before <i>render_burst</i> / <i>end</i>.
<H2> colors </H2>
<p>
In negative drawing mode, drawing an object always clear on the current canvas,
regardless of the GC color.
<p>
In positive drawing mode, objects are drawn with whatever color the
current GC has. The special color "drill" is used to draw holes that go thru
all layers of the board. It is possible that a drill is drawn over existing
objects and new objects are drawn on top of a drilled hole. To get the
proper order, the HID shall set the .holes_after to 1.
<p>
(Note: there's no "erase" color anymore.)
<H2> transition </H2>
<p>
When switching over an existing HID from the old use_mask() API to the new
composite API:
<ul>
<li> set .poly_before to 0
<li> set .poly_after to 0
<li> set .enable_fake_composite to 0
<li> set .holes_after to 1
<li> use an empty function for .use_mask for now
</ul>
<H2> XOR drawing </H2>
<p>
XOR draw is used as a mean to make an object always visible, no matter
over what background it is drawns. It is <b>not</b> used as a cheap draw/erase
mechanism, so HIDs are free to implement it with a different algorithm - as
long as it is guaranteed that objects drawn on the same colored background
will stick out.
<p>
There are two places XOR draw takes place:
<ul>
<li> in core's normal draw procedures (pcb_hid_expose*()), as the very last
compsiting canvas (after everything else had been drawn)
<li> in pcb_draw_attached(), whenever it is called by the HID
</ul>
<p>
In both cases the drawing mode is set to PCB_HID_COMP_POSITIVE_XOR, which does
<b>not</b> clear the direct flag. The GC that is used for drawing the actual
objects also has its xor mode set.
</body>
</html>
|