Make flattenables no longer depend on global static initializers.
authorscroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 21 Sep 2012 17:54:46 +0000 (17:54 +0000)
committerscroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 21 Sep 2012 17:54:46 +0000 (17:54 +0000)
Instead, force all builds to call InitializeFlattenables.

Remove the make_debugger script, which was created to force
rebuilding without global static initializers so that all flattenables
would be linked. It is no longer necessary since all flattenables
will be linked thanks to InitializeFlattenables, which now can (and
must) be called when global static initializers are turned on.

BUG=https://code.google.com/p/skia/issues/detail?id=903
BUG=https://code.google.com/p/skia/issues/detail?id=902

Review URL: https://codereview.appspot.com/6548044

git-svn-id: http://skia.googlecode.com/svn/trunk@5642 2bbb7eff-a529-9590-31e7-b0007b416f81

43 files changed:
debugger/make_debugger.sh [deleted file]
include/core/SkFlattenable.h
src/core/SkAnnotation.cpp
src/core/SkBitmapProcShader.cpp
src/core/SkColorTable.cpp
src/core/SkComposeShader.cpp
src/core/SkData.cpp
src/core/SkFlattenable.cpp
src/core/SkGraphics.cpp
src/core/SkMallocPixelRef.cpp
src/core/SkPathEffect.cpp
src/core/SkShader.cpp
src/effects/Sk1DPathEffect.cpp
src/effects/Sk2DPathEffect.cpp
src/effects/SkAvoidXfermode.cpp
src/effects/SkBitmapSource.cpp
src/effects/SkBlendImageFilter.cpp
src/effects/SkBlurDrawLooper.cpp
src/effects/SkBlurImageFilter.cpp
src/effects/SkColorFilterImageFilter.cpp
src/effects/SkColorMatrixFilter.cpp
src/effects/SkCornerPathEffect.cpp
src/effects/SkDashPathEffect.cpp
src/effects/SkDiscretePathEffect.cpp
src/effects/SkEmbossMaskFilter.cpp
src/effects/SkLayerDrawLooper.cpp
src/effects/SkLayerRasterizer.cpp
src/effects/SkMagnifierImageFilter.cpp
src/effects/SkMatrixConvolutionImageFilter.cpp
src/effects/SkMorphologyImageFilter.cpp
src/effects/SkPixelXorXfermode.cpp
src/effects/SkRectShape.cpp
src/effects/SkSingleInputImageFilter.cpp
src/effects/SkStippleMaskFilter.cpp
src/effects/SkTestImageFilters.cpp
src/effects/SkTransparentShader.cpp
src/image/SkDataPixelRef.cpp
src/images/SkFlipPixelRef.cpp
src/images/SkImageRef_GlobalPool.cpp
src/ports/SkGlobalInitialization_default.cpp
src/ports/SkImageRef_ashmem.cpp
src/utils/SkUnitMappers.cpp
tests/GLProgramsTest.cpp

diff --git a/debugger/make_debugger.sh b/debugger/make_debugger.sh
deleted file mode 100755 (executable)
index 86a7ff9..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# Used to recompile required skia libraries with static initializers turned
-# off. This fixes a bug in which the linux compiler was incorrectly stripping
-# required global static methods in an optimization effort.
-
-SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-CWD=$SCRIPT_DIR/../
-
-DEFINES="skia_static_initializers=0" 
-export GYP_DEFINES="$DEFINES"
-
-make clean -C $CWD
-make -C $CWD debugger -j 
index 6df9f9b..0b21abc 100644 (file)
 class SkFlattenableReadBuffer;
 class SkFlattenableWriteBuffer;
 
-#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
-
-#define SK_DEFINE_FLATTENABLE_REGISTRAR(flattenable) \
-    static SkFlattenable::Registrar g##flattenable##Reg(#flattenable, \
-                                                       flattenable::CreateProc);
-#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
-    static SkFlattenable::Registrar g##flattenable##Reg(#flattenable, \
-                                                       flattenable::CreateProc);
-
-#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
-#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable)
-#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
-
-#else
-
-#define SK_DEFINE_FLATTENABLE_REGISTRAR(flattenable)
 #define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
         SkFlattenable::Registrar(#flattenable, flattenable::CreateProc);
 
@@ -42,8 +26,6 @@ class SkFlattenableWriteBuffer;
 #define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END \
     }
 
-#endif
-
 #define SK_DECLARE_UNFLATTENABLE_OBJECT() \
     virtual Factory getFactory() SK_OVERRIDE { return NULL; }; \
 
@@ -93,9 +75,7 @@ protected:
     virtual void flatten(SkFlattenableWriteBuffer&) const;
 
 private:
-#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
     static void InitializeFlattenables();
-#endif
 
     friend class SkGraphics;
     friend class SkFlattenableWriteBuffer;
index 62f865d..8176761 100644 (file)
@@ -38,8 +38,6 @@ void SkAnnotation::flatten(SkFlattenableWriteBuffer& buffer) const {
     buffer.writeFlattenable(fDataSet);
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkAnnotation)
-
 const char* SkAnnotationKeys::URL_Key() {
     return "SkAnnotationKey_URL";
 };
index dc669cc..43a6b0a 100644 (file)
@@ -299,8 +299,6 @@ SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
     return shader;
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkBitmapProcShader)
-
 ///////////////////////////////////////////////////////////////////////////////
 
 static const char* gTileModeName[] = {
index 2a27906..1375c58 100644 (file)
@@ -155,5 +155,3 @@ void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
     buffer.writeUInt(fFlags);
     buffer.writeColorArray(fColors, fCount);
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorTable)
index af3f3a5..e925ab5 100644 (file)
@@ -165,6 +165,3 @@ void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
         } while (count > 0);
     }
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkComposeShader)
-
index 4274f2b..3e0c71a 100644 (file)
@@ -141,8 +141,6 @@ SkData::SkData(SkFlattenableReadBuffer& buffer) {
     buffer.readByteArray(const_cast<void*>(fPtr));
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkData)
-
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -302,5 +300,3 @@ SkDataSet* SkDataSet::NewEmpty() {
     gEmptySet->ref();
     return gEmptySet;
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkDataSet)
index 52377c7..b4efe91 100644 (file)
@@ -90,7 +90,7 @@ void SkFlattenable::Register(const char name[], Factory factory) {
     gCount += 1;
 }
 
-#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
+#ifdef SK_DEBUG
 static void report_no_entries(const char* functionName) {
     if (!gCount) {
         SkDebugf("%s has no registered name/factory pairs."
@@ -101,7 +101,7 @@ static void report_no_entries(const char* functionName) {
 #endif
 
 SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
-#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
+#ifdef SK_DEBUG
     report_no_entries(__FUNCTION__);
 #endif
     const Pair* pairs = gPairs;
@@ -114,7 +114,7 @@ SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
 }
 
 const char* SkFlattenable::FactoryToName(Factory fact) {
-#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
+#ifdef SK_DEBUG
     report_no_entries(__FUNCTION__);
 #endif
     const Pair* pairs = gPairs;
index 64f9264..53d0318 100644 (file)
@@ -52,9 +52,7 @@ void SkGraphics::GetVersion(int32_t* major, int32_t* minor, int32_t* patch) {
 #endif
 
 void SkGraphics::Init() {
-#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
     SkFlattenable::InitializeFlattenables();
-#endif
 #ifdef BUILD_EMBOSS_TABLE
     SkEmbossMask_BuildTable();
 #endif
index 71e672b..d700983 100644 (file)
@@ -64,5 +64,3 @@ SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
 
     this->setPreLocked(fStorage, fCTable);
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkMallocPixelRef)
index 84b590d..d706e8d 100644 (file)
@@ -171,9 +171,3 @@ bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src,
     // use bit-or so that we always call both, even if the first one succeeds
     return fPE0->filterPath(dst, src, rec) | fPE1->filterPath(dst, src, rec);
 }
-
-///////////////////////////////////////////////////////////////////////////////
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkComposePathEffect)
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkSumPathEffect)
-
index 40fe838..97cca5f 100644 (file)
@@ -332,8 +332,6 @@ SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
     return kColor_GradientType;
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorShader)
-
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkEmptyShader.h"
@@ -355,5 +353,3 @@ void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
 void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
     SkDEBUGFAIL("should never get called, since setContext() returned false");
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkEmptyShader)
index 6536826..98345d0 100644 (file)
@@ -197,8 +197,3 @@ SkScalar SkPath1DPathEffect::next(SkPath* dst, SkScalar distance,
     }
     return fAdvance;
 }
-
-///////////////////////////////////////////////////////////////////////////////
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkPath1DPathEffect)
-
index 1f1dce4..e4d7821 100644 (file)
@@ -76,8 +76,6 @@ Sk2DPathEffect::Sk2DPathEffect(SkFlattenableReadBuffer& buffer) {
     fMatrixIsInvertible = fMatrix.invert(&fInverse);
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR(Sk2DPathEffect)
-
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkLine2DPathEffect::filterPath(SkPath *dst, const SkPath &src, SkStrokeRec *rec) {
@@ -110,8 +108,6 @@ void SkLine2DPathEffect::flatten(SkFlattenableWriteBuffer &buffer) const {
     buffer.writeScalar(fWidth);
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkLine2DPathEffect)
-
 ///////////////////////////////////////////////////////////////////////////////
 
 SkPath2DPathEffect::SkPath2DPathEffect(const SkMatrix& m, const SkPath& p)
@@ -131,7 +127,3 @@ void SkPath2DPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
 void SkPath2DPathEffect::next(const SkPoint& loc, int u, int v, SkPath* dst) {
     dst->addPath(fPath, loc.fX, loc.fY);
 }
-
-///////////////////////////////////////////////////////////////////////////////
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkPath2DPathEffect)
index f828cca..89ae1f9 100644 (file)
@@ -230,5 +230,3 @@ void SkAvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count, co
 {
     // override in subclass
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkAvoidXfermode)
index 3092b93..8aa0433 100644 (file)
@@ -25,5 +25,3 @@ bool SkBitmapSource::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
     *result = fBitmap;
     return true;
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkBitmapSource)
index 94896a8..2328d95 100644 (file)
@@ -289,5 +289,3 @@ GrGLProgramStage::StageKey GrGLBlendEffect::GenKey(const GrCustomStage& s, const
     return static_cast<const GrBlendEffect&>(s).mode();
 }
 #endif
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkBlendImageFilter)
index 8ba2cfc..e6e2ffd 100644 (file)
@@ -115,8 +115,3 @@ bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
             return false;
     }
 }
-
-///////////////////////////////////////////////////////////////////////////////
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkBlurDrawLooper)
-
index c822626..2a61460 100644 (file)
@@ -197,5 +197,3 @@ GrTexture* SkBlurImageFilter::onFilterImageGPU(GrTexture* src, const SkRect& rec
     return NULL;
 #endif
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkBlurImageFilter)
index 03e2be4..f9c8cef 100755 (executable)
@@ -52,6 +52,3 @@ bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& sourc
     *result = device.get()->accessBitmap(false);
     return true;
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorFilterImageFilter)
-
index 64283ab..2102e9b 100644 (file)
@@ -317,5 +317,3 @@ bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) {
     }
     return true;
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorMatrixFilter)
index bc5165a..1ce62ec 100644 (file)
@@ -137,6 +137,3 @@ void SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
 SkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) {
     fRadius = buffer.readScalar();
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkCornerPathEffect)
-
index 3299c63..3add0d7 100644 (file)
@@ -256,7 +256,3 @@ SkDashPathEffect::SkDashPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(
     fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * fCount);
     buffer.readScalarArray(fIntervals);
 }
-
-///////////////////////////////////////////////////////////////////////////////
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkDashPathEffect)
index d331cdb..8a7c307 100644 (file)
@@ -80,8 +80,3 @@ SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) {
     fSegLength = buffer.readScalar();
     fPerterb = buffer.readScalar();
 }
-
-///////////////////////////////////////////////////////////////////////////////
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkDiscretePathEffect)
-
index 5ced463..6480f50 100644 (file)
@@ -131,5 +131,3 @@ void SkEmbossMaskFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
     buffer.writeByteArray(&tmpLight, sizeof(tmpLight));
     buffer.writeScalar(fBlurRadius);
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkEmbossMaskFilter)
index e4aef18..c27908f 100644 (file)
@@ -245,7 +245,3 @@ SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer)
     }
 #endif
 }
-
-///////////////////////////////////////////////////////////////////////////////
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkLayerDrawLooper)
index a004b30..7365e12 100644 (file)
@@ -169,6 +169,3 @@ void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) const {
         buffer.writePoint(rec->fOffset);
     }
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkLayerRasterizer)
-
index 4eed177..cf64308 100644 (file)
@@ -339,5 +339,3 @@ bool SkMagnifierImageFilter::onFilterImage(Proxy*, const SkBitmap& src,
     }
     return true;
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkMagnifierImageFilter)
index e5acf56..852412b 100644 (file)
@@ -175,5 +175,3 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
     filterBorderPixels(src, result, bottom);
     return true;
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkMatrixConvolutionImageFilter)
index 4123ca8..5bf9a99 100644 (file)
@@ -489,6 +489,3 @@ GrTexture* SkErodeImageFilter::onFilterImageGPU(GrTexture* src, const SkRect& re
 }
 
 #endif
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkDilateImageFilter)
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkErodeImageFilter)
index 236aec5..cf454da 100644 (file)
@@ -28,5 +28,3 @@ SkPixelXorXfermode::SkPixelXorXfermode(SkFlattenableReadBuffer& rb)
         : INHERITED(rb) {
     fOpColor = rb.readColor();
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkPixelXorXfermode)
index 0663106..52c3b37 100644 (file)
@@ -85,6 +85,3 @@ void SkPaintShape::flatten(SkFlattenableWriteBuffer& buffer) const {
 SkPaintShape::SkPaintShape(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
     buffer.readPaint(&fPaint);
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkRectShape)
-
index 291d81c..a1c4292 100644 (file)
@@ -81,5 +81,3 @@ GrTexture* SkSingleInputImageFilter::getInputResultAsTexture(GrTexture* src,
     return resultTex;
 }
 #endif
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkSingleInputImageFilter)
index de5da84..434528e 100644 (file)
@@ -44,5 +44,3 @@ bool SkStippleMaskFilter::filterMask(SkMask* dst,
 
     return true;
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkStippleMaskFilter)
index aeb5d79..d28fda9 100755 (executable)
@@ -343,8 +343,3 @@ void SkDownSampleImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
 SkDownSampleImageFilter::SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
     fScale = buffer.readScalar();
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkOffsetImageFilter)
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkComposeImageFilter)
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkMergeImageFilter)
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkDownSampleImageFilter)
index 419a330..28b075f 100644 (file)
@@ -125,5 +125,3 @@ void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count)
         memcpy(span, src, count << 1);
     }
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkTransparentShader)
index 222519d..980b4f1 100644 (file)
@@ -37,5 +37,3 @@ SkDataPixelRef::SkDataPixelRef(SkFlattenableReadBuffer& buffer)
     fData = (SkData*)buffer.readFlattenable();
     this->setPreLocked(const_cast<void*>(fData->data()), NULL);
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkDataPixelRef)
index f3f54e8..2e73ece 100644 (file)
@@ -75,8 +75,6 @@ SkFlipPixelRef::SkFlipPixelRef(SkFlattenableReadBuffer& buffer)
     buffer.readByteArray(fPage0);
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkFlipPixelRef)
-
 ///////////////////////////////////////////////////////////////////////////////
 
 static void copyRect(const SkBitmap& dst, const SkIRect& rect,
index a5a71a3..e62816a 100644 (file)
@@ -71,8 +71,6 @@ SkImageRef_GlobalPool::SkImageRef_GlobalPool(SkFlattenableReadBuffer& buffer)
     this->mutex()->release();
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkImageRef_GlobalPool)
-
 ///////////////////////////////////////////////////////////////////////////////
 // global imagerefpool wrappers
 
index 7448f8d..fc454b4 100644 (file)
@@ -7,8 +7,6 @@
 
 #include "SkTypes.h"
 
-#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
-
 #include "SkBitmapProcShader.h"
 #include "SkFlipPixelRef.h"
 #include "SkImageRef_ashmem.h"
@@ -99,5 +97,3 @@ void SkFlattenable::InitializeFlattenables() {
     SkTableColorFilter::InitializeFlattenables();
     SkXfermode::InitializeFlattenables();
 }
-
-#endif
index 01b950e..cdd56c8 100644 (file)
@@ -231,5 +231,3 @@ SkImageRef_ashmem::SkImageRef_ashmem(SkFlattenableReadBuffer& buffer)
     }
     this->useDefaultMutex();   // we don't need/want the shared imageref mutex
 }
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkImageRef_ashmem)
index 735a434..ceff9ca 100644 (file)
@@ -59,6 +59,3 @@ uint16_t SkCosineMapper::mapUnit16(uint16_t input)
 
 SkCosineMapper::SkCosineMapper(SkFlattenableReadBuffer& rb)
     : SkUnitMapper(rb) {}
-
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkDiscreteMapper)
-SK_DEFINE_FLATTENABLE_REGISTRAR(SkCosineMapper)
index c1d829c..deaf034 100644 (file)
@@ -27,11 +27,6 @@ int random_int(GrRandom* r, int count) {
     return (int)(r->nextF() * count);
 }
 
-// min is inclusive, max is exclusive
-int random_int(GrRandom* r, int min, int max) {
-    return (int)(r->nextF() * (max-min)) + min;
-}
-
 bool random_bool(GrRandom* r) {
     return r->nextF() > .5f;
 }