diff options
-rw-r--r-- | gyp/gpu.gypi | 1 | ||||
-rw-r--r-- | include/gpu/GrConfig.h | 19 | ||||
-rw-r--r-- | include/gpu/GrTextContext.h | 4 | ||||
-rw-r--r-- | include/gpu/GrUserConfig.h | 7 | ||||
-rw-r--r-- | src/gpu/GrDrawState.cpp | 42 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 7 | ||||
-rw-r--r-- | src/gpu/GrGpuVertex.h | 96 | ||||
-rw-r--r-- | src/gpu/GrTextContext.cpp | 47 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 57 | ||||
-rw-r--r-- | tests/GLProgramsTest.cpp | 4 |
10 files changed, 34 insertions, 250 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index bf301bb012..62137a0e81 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -74,7 +74,6 @@ '<(skia_src_path)/gpu/GrGpu.cpp', '<(skia_src_path)/gpu/GrGpu.h', '<(skia_src_path)/gpu/GrGpuFactory.cpp', - '<(skia_src_path)/gpu/GrGpuVertex.h', '<(skia_src_path)/gpu/GrIndexBuffer.h', '<(skia_src_path)/gpu/GrInOrderDrawBuffer.cpp', '<(skia_src_path)/gpu/GrInOrderDrawBuffer.h', diff --git a/include/gpu/GrConfig.h b/include/gpu/GrConfig.h index 27484811b6..d929d580ac 100644 --- a/include/gpu/GrConfig.h +++ b/include/gpu/GrConfig.h @@ -315,16 +315,6 @@ inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); } #endif #endif -#if !defined(GR_TEXT_SCALAR_TYPE_IS_USHORT) - #define GR_TEXT_SCALAR_TYPE_IS_USHORT 0 -#endif -#if !defined(GR_TEXT_SCALAR_TYPE_IS_FLOAT) - #define GR_TEXT_SCALAR_TYPE_IS_FLOAT 0 -#endif -#if !defined(GR_TEXT_SCALAR_TYPE_IS_FIXED) - #define GR_TEXT_SCALAR_TYPE_IS_FIXED 0 -#endif - /** * GR_GEOM_BUFFER_LOCK_THRESHOLD gives a threshold (in bytes) for when Gr should * lock a GrGeometryBuffer to update its contents. It will use lock() if the @@ -379,15 +369,6 @@ inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); } #error "More than one GR_BUILD defined" #endif - -#if !GR_TEXT_SCALAR_IS_FLOAT && \ - !GR_TEXT_SCALAR_IS_FIXED && \ - !GR_TEXT_SCALAR_IS_USHORT - #undef GR_TEXT_SCALAR_IS_FLOAT - #define GR_TEXT_SCALAR_IS_FLOAT 1 - #pragma message GR_WARN("Text scalar type not defined, defaulting to float") -#endif - #if 0 #if GR_WIN32_BUILD // #pragma message GR_WARN("GR_WIN32_BUILD") diff --git a/include/gpu/GrTextContext.h b/include/gpu/GrTextContext.h index fc7735db7a..f329fdefd1 100644 --- a/include/gpu/GrTextContext.h +++ b/include/gpu/GrTextContext.h @@ -15,7 +15,6 @@ #include "GrGlyph.h" #include "GrPaint.h" -struct GrGpuTextVertex; class GrContext; class GrTextStrike; class GrFontScaler; @@ -50,8 +49,7 @@ private: kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4, }; - GrGpuTextVertex* fVertices; - + SkPoint* fVertices; int32_t fMaxVertices; GrTexture* fCurrTexture; int fCurrVertex; diff --git a/include/gpu/GrUserConfig.h b/include/gpu/GrUserConfig.h index 18ebb225cb..b9df083c48 100644 --- a/include/gpu/GrUserConfig.h +++ b/include/gpu/GrUserConfig.h @@ -34,11 +34,4 @@ */ //#define GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT 96 -/////////////////////////////////////////////////////////////////////////////// -// Decide Ganesh types - -#define GR_TEXT_SCALAR_IS_USHORT 0 -#define GR_TEXT_SCALAR_IS_FIXED 0 -#define GR_TEXT_SCALAR_IS_FLOAT 1 - #endif diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index b6c521f093..5b434c3d7f 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -6,8 +6,6 @@ */ #include "GrDrawState.h" - -#include "GrGpuVertex.h" #include "GrPaint.h" void GrDrawState::setFromPaint(const GrPaint& paint) { @@ -149,15 +147,13 @@ int num_tex_coords(GrVertexLayout layout) { } //unnamed namespace +static const size_t kVec2Size = sizeof(GrPoint); + size_t GrDrawState::VertexSize(GrVertexLayout vertexLayout) { GrAssert(check_layout(vertexLayout)); - size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? - sizeof(GrGpuTextVertex) : - sizeof(GrPoint); - - size_t size = vecSize; // position - size += num_tex_coords(vertexLayout) * vecSize; + size_t size = kVec2Size; // position + size += num_tex_coords(vertexLayout) * kVec2Size; if (vertexLayout & kColor_VertexLayoutBit) { size += sizeof(GrColor); } @@ -194,14 +190,11 @@ int GrDrawState::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayou int tcIdx = VertexTexCoordsForStage(stageIdx, vertexLayout); if (tcIdx >= 0) { - int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? - sizeof(GrGpuTextVertex) : - sizeof(GrPoint); - int offset = vecSize; // position + int offset = kVec2Size; // position // figure out how many tex coordinates are present and precede this one. for (int t = 0; t < tcIdx; ++t) { if (gTexCoordMasks[t] & vertexLayout) { - offset += vecSize; + offset += kVec2Size; } } return offset; @@ -214,10 +207,7 @@ int GrDrawState::VertexColorOffset(GrVertexLayout vertexLayout) { GrAssert(check_layout(vertexLayout)); if (vertexLayout & kColor_VertexLayoutBit) { - int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? - sizeof(GrGpuTextVertex) : - sizeof(GrPoint); - return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos + return kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos } return -1; } @@ -226,11 +216,7 @@ int GrDrawState::VertexCoverageOffset(GrVertexLayout vertexLayout) { GrAssert(check_layout(vertexLayout)); if (vertexLayout & kCoverage_VertexLayoutBit) { - int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? - sizeof(GrGpuTextVertex) : - sizeof(GrPoint); - - int offset = vecSize * (num_tex_coords(vertexLayout) + 1); + int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1); if (vertexLayout & kColor_VertexLayoutBit) { offset += sizeof(GrColor); } @@ -244,10 +230,7 @@ int GrDrawState::VertexEdgeOffset(GrVertexLayout vertexLayout) { // edge pts are after the pos, tex coords, and color if (vertexLayout & kEdge_VertexLayoutBit) { - int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? - sizeof(GrGpuTextVertex) : - sizeof(GrPoint); - int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos + int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos if (vertexLayout & kColor_VertexLayoutBit) { offset += sizeof(GrColor); } @@ -267,17 +250,14 @@ int GrDrawState::VertexSizeAndOffsetsByIdx( int* edgeOffset) { GrAssert(check_layout(vertexLayout)); - int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ? - sizeof(GrGpuTextVertex) : - sizeof(GrPoint); - int size = vecSize; // position + int size = kVec2Size; // position for (int t = 0; t < kMaxTexCoords; ++t) { if (gTexCoordMasks[t] & vertexLayout) { if (NULL != texCoordOffsetsByIdx) { texCoordOffsetsByIdx[t] = size; } - size += vecSize; + size += kVec2Size; } else { if (NULL != texCoordOffsetsByIdx) { texCoordOffsetsByIdx[t] = -1; diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index de23df7650..2245e05bd1 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -164,15 +164,10 @@ public: /* vertices have coverage (GrColor) */ kCoverage_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 1), - /* Use text vertices. (Pos and tex coords may be a different type for - * text [GrGpuTextVertex vs GrPoint].) - */ - kTextFormat_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 2), - /* Each vertex specificies an edge. Distance to the edge is used to * compute a coverage. See GrDrawState::setVertexEdgeType(). */ - kEdge_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 3), + kEdge_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 2), // for below assert kDummyVertexLayoutBit, kHighVertexLayoutBit = kDummyVertexLayoutBit - 1 diff --git a/src/gpu/GrGpuVertex.h b/src/gpu/GrGpuVertex.h deleted file mode 100644 index 19a0b01e54..0000000000 --- a/src/gpu/GrGpuVertex.h +++ /dev/null @@ -1,96 +0,0 @@ - -/* - * Copyright 2010 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - - -#ifndef GrGpuVertex_DEFINED -#define GrGpuVertex_DEFINED - -#include "gl/GrGLConfig.h" -#include "GrPoint.h" - -#if GR_TEXT_SCALAR_IS_USHORT - typedef uint16_t GrTextScalar; - #define GrIntToTextScalar(x) ((uint16_t)x) - #define GrFixedToTextScalar(x) (x) -#elif GR_TEXT_SCALAR_IS_FIXED - typedef GrFixed GrTextScalar; - #define GrIntToTextScalar(x) SkIntToFixed(x) - #define GrFixedToTextScalar(x) (x) -#elif GR_TEXT_SCALAR_IS_FLOAT - typedef float GrTextScalar; - #define GrIntToTextScalar(x) ((GrTextScalar)x) - #define GrFixedToTextScalar(x) SkFixedToFloat(x) -#else - #error "Text scalar type not defined" -#endif - -// text has its own vertex class, since it may want to be in fixed point (given) -// that it starts with all integers) even when the default vertices are floats -struct GrGpuTextVertex { - GrTextScalar fX; - GrTextScalar fY; - - void set(GrTextScalar x, GrTextScalar y) { - fX = x; - fY = y; - } - - void setI(int x, int y) { - fX = GrIntToTextScalar(x); - fY = GrIntToTextScalar(y); - } - - void setX(GrFixed x, GrFixed y) { - fX = GrFixedToTextScalar(x); - fY = GrFixedToTextScalar(y); - } - - // rect fan is counter-clockwise - - void setRectFan(GrTextScalar l, GrTextScalar t, GrTextScalar r, - GrTextScalar b) { - GrGpuTextVertex* v = this; - v[0].set(l, t); - v[1].set(l, b); - v[2].set(r, b); - v[3].set(r, t); - } - - void setIRectFan(int l, int t, int r, int b) { - this->setRectFan(GrIntToTextScalar(l), GrIntToTextScalar(t), - GrIntToTextScalar(r), GrIntToTextScalar(b)); - } - - void setIRectFan(int l, int t, int r, int b, size_t stride) { - GrAssert(stride > sizeof(GrGpuTextVertex)); - char* v = (char*)this; - ((GrGpuTextVertex*)(v + 0*stride))->setI(l, t); - ((GrGpuTextVertex*)(v + 1*stride))->setI(l, b); - ((GrGpuTextVertex*)(v + 2*stride))->setI(r, b); - ((GrGpuTextVertex*)(v + 3*stride))->setI(r, t); - } - - // counter-clockwise fan - void setXRectFan(GrFixed l, GrFixed t, GrFixed r, GrFixed b) { - this->setRectFan(GrFixedToTextScalar(l), GrFixedToTextScalar(t), - GrFixedToTextScalar(r), GrFixedToTextScalar(b)); - } - - void setXRectFan(GrFixed l, GrFixed t, GrFixed r, GrFixed b, size_t stride) { - GrAssert(stride > sizeof(GrGpuTextVertex)); - char* v = (char*)this; - ((GrGpuTextVertex*)(v + 0*stride))->setX(l, t); - ((GrGpuTextVertex*)(v + 1*stride))->setX(l, b); - ((GrGpuTextVertex*)(v + 2*stride))->setX(r, b); - ((GrGpuTextVertex*)(v + 3*stride))->setX(r, t); - } - -}; - -#endif diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index b1973a6e89..0a819da4c6 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -12,7 +12,6 @@ #include "GrContext.h" #include "GrDrawTarget.h" #include "GrFontScaler.h" -#include "GrGpuVertex.h" #include "GrIndexBuffer.h" #include "GrTextStrike.h" #include "GrTextStrike_impl.h" @@ -94,9 +93,7 @@ GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint) : fPaint( fVertices = NULL; fMaxVertices = 0; - fVertexLayout = - GrDrawState::kTextFormat_VertexLayoutBit | - GrDrawState::StageTexCoordVertexLayoutBit(kGlyphMaskStage, 0); + fVertexLayout = GrDrawState::StageTexCoordVertexLayoutBit(kGlyphMaskStage, 0); } GrTextContext::~GrTextContext() { @@ -110,14 +107,6 @@ void GrTextContext::flush() { this->flushGlyphs(); } -static inline void setRectFan(GrGpuTextVertex v[4], int l, int t, int r, int b, - int stride) { - v[0 * stride].setI(l, t); - v[1 * stride].setI(l, b); - v[2 * stride].setI(r, b); - v[3 * stride].setI(r, t); -} - void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, GrFixed vx, GrFixed vy, GrFontScaler* scaler) { @@ -186,7 +175,7 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, HAS_ATLAS: GrAssert(glyph->fAtlas); - // now promote them to fixed + // now promote them to fixed (TODO: Rethink using fixed pt). width = SkIntToFixed(width); height = SkIntToFixed(height); @@ -238,27 +227,15 @@ HAS_ATLAS: GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); -#if GR_TEXT_SCALAR_IS_USHORT - int x = vx >> 16; - int y = vy >> 16; - int w = width >> 16; - int h = height >> 16; - - setRectFan(&fVertices[2*fCurrVertex], x, y, x + w, y + h, 2); - setRectFan(&fVertices[2*fCurrVertex+1], - texture->normalizeFixedX(tx), - texture->normalizeFixedY(ty), - texture->normalizeFixedX(tx + width), - texture->normalizeFixedY(ty + height), - 2); -#else - fVertices[2*fCurrVertex].setXRectFan(vx, vy, vx + width, vy + height, - 2 * sizeof(GrGpuTextVertex)); - fVertices[2*fCurrVertex+1].setXRectFan(texture->normalizeFixedX(tx), - texture->normalizeFixedY(ty), - texture->normalizeFixedX(tx + width), - texture->normalizeFixedY(ty + height), - 2 * sizeof(GrGpuTextVertex)); -#endif + fVertices[2*fCurrVertex].setRectFan(SkFixedToFloat(vx), + SkFixedToFloat(vy), + SkFixedToFloat(vx + width), + SkFixedToFloat(vy + height), + 2 * sizeof(SkPoint)); + fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)), + SkFixedToFloat(texture->normalizeFixedY(ty)), + SkFixedToFloat(texture->normalizeFixedX(tx + width)), + SkFixedToFloat(texture->normalizeFixedY(ty + height)), + 2 * sizeof(SkPoint)); fCurrVertex += 4; } diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index 7a3ae4cd6c..a566f3f7fb 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -9,7 +9,6 @@ #include "GrEffect.h" #include "GrGLEffect.h" -#include "GrGpuVertex.h" typedef GrGLUniformManager::UniformHandle UniformHandle; static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle; @@ -343,19 +342,6 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { return true; } -#if GR_TEXT_SCALAR_IS_USHORT - #define TEXT_COORDS_GL_TYPE GR_GL_UNSIGNED_SHORT - #define TEXT_COORDS_ARE_NORMALIZED 1 -#elif GR_TEXT_SCALAR_IS_FLOAT - #define TEXT_COORDS_GL_TYPE GR_GL_FLOAT - #define TEXT_COORDS_ARE_NORMALIZED 0 -#elif GR_TEXT_SCALAR_IS_FIXED - #define TEXT_COORDS_GL_TYPE GR_GL_FIXED - #define TEXT_COORDS_ARE_NORMALIZED 0 -#else - #error "unknown GR_TEXT_SCALAR type" -#endif - void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { int newColorOffset; @@ -384,16 +370,6 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { int extraVertexOffset; this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset); - GrGLenum scalarType; - bool texCoordNorm; - if (currLayout & GrDrawState::kTextFormat_VertexLayoutBit) { - scalarType = TEXT_COORDS_GL_TYPE; - texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED); - } else { - scalarType = GR_GL_FLOAT; - texCoordNorm = false; - } - size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride; // all the Pointers must be set if any of these are true @@ -401,17 +377,9 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { vertexOffset != fHWGeometryState.fVertexOffset || newStride != oldStride; - // position and tex coord offsets change if above conditions are true - // or the type/normalization changed based on text vs nontext type coords. - bool posAndTexChange = allOffsetsChange || - (((TEXT_COORDS_GL_TYPE != GR_GL_FLOAT) || TEXT_COORDS_ARE_NORMALIZED) && - (GrDrawState::kTextFormat_VertexLayoutBit & - (fHWGeometryState.fVertexLayout ^ currLayout))); - - if (posAndTexChange) { + if (allOffsetsChange) { int idx = GrGLProgram::PositionAttributeIdx(); - GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride, - (GrGLvoid*)vertexOffset)); + GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, (GrGLvoid*)vertexOffset)); fHWGeometryState.fVertexOffset = vertexOffset; } @@ -421,12 +389,9 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { int idx = GrGLProgram::TexCoordAttributeIdx(t); if (oldTexCoordOffsets[t] <= 0) { GL_CALL(EnableVertexAttribArray(idx)); - GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, - newStride, texCoordOffset)); - } else if (posAndTexChange || - newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { - GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, - newStride, texCoordOffset)); + GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset)); + } else if (allOffsetsChange || newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { + GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset)); } } else if (oldTexCoordOffsets[t] > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); @@ -438,11 +403,9 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { int idx = GrGLProgram::ColorAttributeIdx(); if (oldColorOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); - GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, - true, newStride, colorOffset)); + GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } else if (allOffsetsChange || newColorOffset != oldColorOffset) { - GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, - true, newStride, colorOffset)); + GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } } else if (oldColorOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); @@ -468,11 +431,9 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { int idx = GrGLProgram::EdgeAttributeIdx(); if (oldEdgeOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); - GL_CALL(VertexAttribPointer(idx, 4, scalarType, - false, newStride, edgeOffset)); + GL_CALL(VertexAttribPointer(idx, 4, GR_GL_FLOAT, false, newStride, edgeOffset)); } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) { - GL_CALL(VertexAttribPointer(idx, 4, scalarType, - false, newStride, edgeOffset)); + GL_CALL(VertexAttribPointer(idx, 4, GR_GL_FLOAT, false, newStride, edgeOffset)); } } else if (oldEdgeOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx())); diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 743b55447a..958da9502b 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -119,10 +119,6 @@ bool GrGpuGL::programUnitTest(int maxStages) { int t = random_int(&random, GrDrawState::kMaxTexCoords); pdesc.fVertexLayout |= GrDrawState::StageTexCoordVertexLayoutBit(s, t); } - // use text-formatted verts? - if (random_bool(&random)) { - pdesc.fVertexLayout |= GrDrawState::kTextFormat_VertexLayoutBit; - } GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; SkAutoTUnref<const GrEffectRef> effect(create_random_effect(&random, |