Simple function generator: is current-limiting/short circuit protection/impedance matching necessary?
Unless the amount of power a piece of laboratory equipment will ever be called upon to deliver is too large to be dissipated within the equipment itself, there's often no particular reason why such equipment should attempt to drive signals hard enough that it damages itself in the attempt.  It's easy to build a current-limiting circuit using linear electronics if one is willing to heat sink it adequately to dissipate power equal to the source voltage times the limit current [or else set the limit current low enough that no heat-sinking is necessary].  Unless someone is trying to make something unusually powerful or unusually compact (by lab-equipment standards) there's no real reason not to include such heat-sinking.  If extended operation under high-dissipation conditions is not expected, the heat sink may only need to be good enough to ensure that a thermal-cutout sensor will trip before other devices on the heat sink are damaged.

It may be also helpful when designing a logic-controlled function generator to have a circuit that can report whether the actual output waveform is within a certain tolerance of the specified waveform.  For this to be useful, it may be necessary to replace "square waves" with configurable-slope "trapezoid waves".  If one attempts to use crudely-current-limited outputs to drive a somewhat-capacitive load with a sharp-edged square wave, the edges are likely to end up with weird and uneven slopes.  Using edges with programmed slopes will likely yield much better results.

For digital function-generator purposes, I would suggest having at absolute minimum a 10:1 ratio between the sample rate and the desired output frequency; a 100:1 ratio would be better.  If you use a high enough ratio, even very crude filtering circuitry on the output of the DAC will be sufficient to yield good results.  It might be possible to get good results using a lower sample rate using better filter circuitry, but if your goal is to generate waveforms up to 1MHz, using a 50MHz clock might be easier than designing filtering sufficient to yield acceptable results with a 10MHz clock.

Although most DAC-based waveform-generation approaches use at least a second-order anti-aliasing filter to "smooth" the output waveform, I would suggest taking the opposite approach.  Use an op amp to build a first-order low-pass filter with a very low cut-off frequency but very high gain (basically an integrator) and either use software to compute the inverse function of that filter (pretty straightforward) or, or use a "pure" integrator (zero cutoff frequency) and an ADC and software-based feedback.  You'll need to make sure that you update the waveform fed to the DAC precisely at the inflection points, but you should be able to get much cleaner output waveforms than using more typical approaches.

Using either approach, the goal would be to have software determine for each sample what value it should output to the DAC to make the output waveform ramp toward the voltage it's supposed to have at the time of the next sample.  Consider the following integrator circuit:







simulate this circuit &ndash; Schematic created using CircuitLab

If at some moment in time the output is at voltage X, and one wishes to be at voltage Y one microsecond later, one should feed the circuit an input of (2.5+(Y-X)+(X+Y)/200) volts which will cause the output to ramp smoothly to that new voltage.  This calculation isn't quite exact, but it should turn out pretty close.  Accuracy/resolution at low frequencies could be enhanced by increasing C1 or R5.  The "/200" factor in the above equation is the twice the ratio of R1 to R5 [doubled because the formula is taking the average of X and Y], so changing C1 would not affect that ratio but changing R1 would.