diff options
Diffstat (limited to 'Runtime/GfxDevice/null')
-rw-r--r-- | Runtime/GfxDevice/null/GfxDeviceNull.cpp | 251 | ||||
-rw-r--r-- | Runtime/GfxDevice/null/GfxDeviceNull.h | 158 | ||||
-rw-r--r-- | Runtime/GfxDevice/null/GfxNullVBO.cpp | 107 | ||||
-rw-r--r-- | Runtime/GfxDevice/null/GfxNullVBO.h | 55 |
4 files changed, 571 insertions, 0 deletions
diff --git a/Runtime/GfxDevice/null/GfxDeviceNull.cpp b/Runtime/GfxDevice/null/GfxDeviceNull.cpp new file mode 100644 index 0000000..4981f54 --- /dev/null +++ b/Runtime/GfxDevice/null/GfxDeviceNull.cpp @@ -0,0 +1,251 @@ +#include "UnityPrefix.h" +#include "GfxDeviceNull.h" +#include "Runtime/Shaders/GraphicsCaps.h" +#include "Runtime/Graphics/RenderSurface.h" +#include "GfxNullVBO.h" +#include "Runtime/GfxDevice/GfxDeviceWindow.h" +#include "External/shaderlab/Library/program.h" + + +static DeviceBlendState g_NullBlendState; +static DeviceDepthState g_NullDepthState; +static DeviceStencilState g_NullStencilState; +static DeviceRasterState g_NullRasterState; + +static float g_NullWorldMatrix[16]; +static float g_NullViewMatrix[16]; +static float g_NullProjectionMatrix[16]; + +static RenderSurfaceBase _ColorDefaultSurface; +static RenderSurfaceBase _DepthDefaultSurface; + + +void GraphicsCaps::InitNull(void) +{ + rendererString = "Null Device"; + vendorString = "Unity Technologies"; + driverVersionString = "1.0"; + fixedVersionString = "NULL 1.0 [1.0]"; + driverLibraryString = "(null)"; + videoMemoryMB = 64.0f; + rendererID = 0; + vendorID = 0; + + printf_console( "NullGfxDevice:\n" ); + printf_console( " Version: %s\n", fixedVersionString.c_str() ); + printf_console( " Renderer: %s\n", rendererString.c_str() ); + printf_console( " Vendor: %s\n", vendorString.c_str() ); + + shaderCaps = kShaderLevel2; + + maxLights = 8; + hasAnisoFilter = false; + maxAnisoLevel = 0; + hasMipLevelBias = false; + + hasMultiSample = false; + + hasBlendSquare = false; + hasSeparateAlphaBlend = false; + + hasS3TCCompression = false; + + hasAutoMipMapGeneration = false; + + maxTexImageUnits = 2; + maxTexCoords = 2; + + + maxTexUnits = 2; + + maxTextureSize = 1024; + maxCubeMapSize = 0; + maxRenderTextureSize = 0; + + for (int i = 0; i < kRTFormatCount; ++i) + { + supportsRenderTextureFormat[i] = false; + } + + has3DTexture = false; + npotRT = npot = kNPOTNone; + + hasRenderToTexture = false; + hasRenderToCubemap = false; + hasRenderTargetStencil = false; + hasTwoSidedStencil = false; + hasHighPrecisionTextureCombiners = false; + hasNativeDepthTexture = false; + hasStencilInDepthTexture = false; + hasNativeShadowMap = false; + + needsToSwizzleVertexColors = false; +} + + +GfxDevice* CreateNullGfxDevice() +{ + ::gGraphicsCaps.InitNull(); + + return UNITY_NEW_AS_ROOT(GfxDeviceNull(), kMemGfxDevice, "NullGfxDevice",""); +} + +GfxDeviceNull::GfxDeviceNull(void) +: dynamicVBO(NULL) +{ + InvalidateState(); + ResetFrameStats(); + + m_Renderer = kGfxRendererNull; + m_UsesOpenGLTextureCoords = false; + m_UsesHalfTexelOffset = false; + m_MaxBufferedFrames = -1; // no limiting + + RenderSurfaceBase_InitColor(_ColorDefaultSurface); + _ColorDefaultSurface.backBuffer = true; + SetBackBufferColorSurface(&_ColorDefaultSurface); + + RenderSurfaceBase_InitDepth(_DepthDefaultSurface); + _DepthDefaultSurface.backBuffer = true; + SetBackBufferDepthSurface(&_DepthDefaultSurface); +} + +GfxDeviceNull::~GfxDeviceNull(void) +{ + delete this->dynamicVBO; +} + +void GfxDeviceNull::GetMatrix( float outMatrix[16] ) const +{ + for( int i = 0; i < 16; ++i ) + outMatrix[i] = 0.0f; +} + + +void GfxDeviceNull::GetViewport( int* port ) const +{ + AssertIf(!port); + port[0] = 0; + port[1] = 0; + port[2] = 1; + port[3] = 1; +} + + +void GfxDeviceNull::GetScissorRect( int scissor[4] ) const +{ + AssertIf(!scissor); + scissor[0] = 0; + scissor[1] = 0; + scissor[2] = 1; + scissor[3] = 1; +} + +TextureCombinersHandle GfxDeviceNull::CreateTextureCombiners( int count, const ShaderLab::TextureBinding* texEnvs, const ShaderLab::PropertySheet* props, bool hasVertexColorOrLighting, bool usesAddSpecular ) +{ + return TextureCombinersHandle(this); // just have to pass non-NULL to the handle +} + +void GfxDeviceNull::DeleteTextureCombiners( TextureCombinersHandle& textureCombiners ) +{ + textureCombiners.Reset(); +} + +void GfxDeviceNull::DestroySubProgram( ShaderLab::SubProgram* subprogram ) +{ + delete subprogram; +} + +VBO* GfxDeviceNull::CreateVBO() +{ + VBO* vbo = new GfxNullVBO(); + OnCreateVBO(vbo); + return vbo; +} + +void GfxDeviceNull::DeleteVBO( VBO* vbo ) +{ + AssertIf(!vbo); + OnDeleteVBO(vbo); + delete vbo; +} + +DynamicVBO& GfxDeviceNull::GetDynamicVBO() +{ + if (NULL == this->dynamicVBO) + { + this->dynamicVBO = new GfxDynamicNullVBO(); + } + + return *this->dynamicVBO; +} + + + +bool GfxDeviceNull::CaptureScreenshot( int left, int bottom, int width, int height, UInt8* rgba32 ) +{ + return true; +} + + +bool GfxDeviceNull::ReadbackImage( ImageReference& image, int left, int bottom, int width, int height, int destX, int destY ) +{ + return true; +} + +DeviceBlendState* GfxDeviceNull::CreateBlendState(const GfxBlendState& state) +{ + return & g_NullBlendState; +} + +DeviceDepthState* GfxDeviceNull::CreateDepthState(const GfxDepthState& state) +{ + return & g_NullDepthState; +} + +DeviceStencilState* GfxDeviceNull::CreateStencilState(const GfxStencilState& state) +{ + return & g_NullStencilState; +} + +DeviceRasterState* GfxDeviceNull::CreateRasterState(const GfxRasterState& state) +{ + return & g_NullRasterState; +} + +const float* GfxDeviceNull::GetWorldMatrix() const +{ + return g_NullWorldMatrix; +} + +const float* GfxDeviceNull::GetViewMatrix() const +{ + return g_NullViewMatrix; +} + +const float* GfxDeviceNull::GetProjectionMatrix() const +{ + return g_NullProjectionMatrix; +} + + + +RenderSurfaceHandle GfxDeviceNull::CreateRenderColorSurface (TextureID textureID, int width, int height, int samples, int depth, TextureDimension dim, RenderTextureFormat format, UInt32 createFlags) +{ + return RenderSurfaceHandle(&_ColorDefaultSurface); +} +RenderSurfaceHandle GfxDeviceNull::CreateRenderDepthSurface (TextureID textureID, int width, int height, int samples, TextureDimension dim, DepthBufferFormat depthFormat, UInt32 createFlags) +{ + return RenderSurfaceHandle(&_DepthDefaultSurface); +} + +// -------- editor only functions + +#if UNITY_EDITOR + +GfxDeviceWindow* GfxDeviceNull::CreateGfxWindow( HWND window, int width, int height, DepthBufferFormat depthFormat, int antiAlias ) +{ + return new GfxDeviceWindow(window,width, height, depthFormat, antiAlias); +} + +#endif diff --git a/Runtime/GfxDevice/null/GfxDeviceNull.h b/Runtime/GfxDevice/null/GfxDeviceNull.h new file mode 100644 index 0000000..d96d016 --- /dev/null +++ b/Runtime/GfxDevice/null/GfxDeviceNull.h @@ -0,0 +1,158 @@ +#pragma once + +#include "Runtime/GfxDevice/GfxDevice.h" + + + +class GfxDeviceNull : public GfxDevice +{ +public: + GfxDeviceNull(); + GFX_API ~GfxDeviceNull(); + + GFX_API void InvalidateState() { } + #if GFX_DEVICE_VERIFY_ENABLE + GFX_API void VerifyState() { } + #endif + + GFX_API void Clear (UInt32 clearFlags, const float color[4], float depth, int stencil) { } + GFX_API void SetUserBackfaceMode( bool enable ) { } + GFX_API void SetWireframe(bool wire) { } + GFX_API bool GetWireframe() const { return false; } + GFX_API void SetInvertProjectionMatrix( bool enable ) { } + GFX_API bool GetInvertProjectionMatrix() const { return false; } + + GFX_API void SetWorldMatrix( const float matrix[16] ) {}; + GFX_API void SetViewMatrix( const float matrix[16] ) {}; + GFX_API void SetProjectionMatrix (const Matrix4x4f& matrix) { } + GFX_API void GetMatrix( float outMatrix[16] ) const; + + GFX_API const float* GetWorldMatrix() const; + GFX_API const float* GetViewMatrix() const; + GFX_API const float* GetProjectionMatrix() const; + GFX_API const float* GetDeviceProjectionMatrix() const { return GetProjectionMatrix(); } + + GFX_API void SetNormalizationBackface( NormalizationMode mode, bool backface ) { } + GFX_API void SetAlpha( BlendMode src, BlendMode dst, CompareFunction mode, float value, bool alphaToMask ) { } + GFX_API void SetFFLighting( bool on, bool separateSpecular, ColorMaterialMode colorMaterial ) {} + GFX_API void SetMaterial( const float ambient[4], const float diffuse[4], const float specular[4], const float emissive[4], const float shininess ) { } + GFX_API void SetColor( const float color[4] ) { } + GFX_API void SetViewport( int x, int y, int width, int height ) { } + GFX_API void GetViewport( int* port ) const; + + GFX_API void SetScissorRect( int x, int y, int width, int height ) { } + GFX_API void DisableScissor() { } + GFX_API bool IsScissorEnabled() const { return false; } + GFX_API void GetScissorRect( int values[4] ) const; + GFX_API void DiscardContents (RenderSurfaceHandle& rs) {} + + GFX_API TextureCombinersHandle CreateTextureCombiners( int count, const ShaderLab::TextureBinding* texEnvs, const ShaderLab::PropertySheet* props, bool hasVertexColorOrLighting, bool usesAddSpecular ); + GFX_API void DeleteTextureCombiners( TextureCombinersHandle& texturesCombiners ); + GFX_API void SetTextureCombiners( TextureCombinersHandle texturesCombiners, const ShaderLab::PropertySheet* props ) { } + + GFX_API void SetTexture (ShaderType shaderType, int unit, int samplerUnit, TextureID texture, TextureDimension dim, float bias) { } + GFX_API void SetTextureParams( TextureID texture, TextureDimension texDim, TextureFilterMode filter, TextureWrapMode wrap, int anisoLevel, bool hasMipMap, TextureColorSpace colorSpace ) { } + GFX_API void SetTextureTransform( int unit, TextureDimension dim, TexGenMode texGen, bool identity, const float matrix[16]) { } + GFX_API void SetTextureName ( TextureID texture, const char* name ) { } + + GFX_API void SetShadersMainThread( ShaderLab::SubProgram* programs[kShaderTypeCount], const ShaderLab::PropertySheet* props ) { } + GFX_API bool IsShaderActive( ShaderType type ) const { return false; } + GFX_API void DestroySubProgram( ShaderLab::SubProgram* subprogram ); + + GFX_API void DisableLights( int startLight ) { } + GFX_API void SetLight( int light, const GfxVertexLight& data) { } + GFX_API void SetAmbient( const float ambient[4] ) { } + + GFX_API void EnableFog (const GfxFogParams& fog) { } + GFX_API void DisableFog() { } + + GFX_API GPUSkinningInfo *CreateGPUSkinningInfo() { return NULL; } + GFX_API void DeleteGPUSkinningInfo(GPUSkinningInfo *info) { AssertBreak(false); } + GFX_API void SkinOnGPU( GPUSkinningInfo * info, bool lastThisFrame ) { AssertBreak(false); } + GFX_API void UpdateSkinSourceData(GPUSkinningInfo *info, const void *vertData, const BoneInfluence *skinData, bool dirty) { AssertBreak(false); } + GFX_API void UpdateSkinBonePoses(GPUSkinningInfo *info, const int boneCount, const Matrix4x4f* poses) { AssertBreak(false); } + + GFX_API VBO* CreateVBO(); + GFX_API void DeleteVBO( VBO* vbo ); + GFX_API DynamicVBO& GetDynamicVBO(); + + GFX_API RenderSurfaceHandle CreateRenderColorSurface (TextureID textureID, int width, int height, int samples, int depth, TextureDimension dim, RenderTextureFormat format, UInt32 createFlags); + GFX_API RenderSurfaceHandle CreateRenderDepthSurface (TextureID textureID, int width, int height, int samples, TextureDimension dim, DepthBufferFormat depthFormat, UInt32 createFlags); + GFX_API void DestroyRenderSurface (RenderSurfaceHandle& rs) {} + GFX_API void SetRenderTargets (int count, RenderSurfaceHandle* colorHandles, RenderSurfaceHandle depthHandle, int mipLevel, CubemapFace face = kCubeFaceUnknown) {} + GFX_API void ResolveColorSurface (RenderSurfaceHandle srcHandle, RenderSurfaceHandle dstHandle) { } + GFX_API RenderSurfaceHandle GetActiveRenderColorSurface (int index) { return RenderSurfaceHandle(); } + GFX_API RenderSurfaceHandle GetActiveRenderDepthSurface () { return RenderSurfaceHandle(); } + GFX_API void SetSurfaceFlags(RenderSurfaceHandle surf, UInt32 flags, UInt32 keepFlags) { } + + GFX_API void UploadTexture2D( TextureID texture, TextureDimension dimension, UInt8* srcData, int srcSize, int width, int height, TextureFormat format, int mipCount, UInt32 uploadFlags, int skipMipLevels, TextureUsageMode usageMode, TextureColorSpace colorSpace ) { } + GFX_API void UploadTextureSubData2D( TextureID texture, UInt8* srcData, int srcSize, int mipLevel, int x, int y, int width, int height, TextureFormat format, TextureColorSpace colorSpace ) { } + GFX_API void UploadTextureCube( TextureID texture, UInt8* srcData, int srcSize, int faceDataSize, int size, TextureFormat format, int mipCount, UInt32 uploadFlags, TextureColorSpace colorSpace ) { } + GFX_API void UploadTexture3D( TextureID texture, UInt8* srcData, int srcSize, int width, int height, int depth, TextureFormat format, int mipCount, UInt32 uploadFlags ) { } + GFX_API void DeleteTexture( TextureID texture ) { } + + GFX_API PresentMode GetPresentMode() { return kPresentBeforeUpdate; } + + GFX_API void BeginFrame() { m_InsideFrame = true; } + GFX_API void EndFrame() { m_InsideFrame = false; } + GFX_API void PresentFrame() { } + GFX_API bool IsValidState() { return true; } + + GFX_API void FinishRendering() { } + + // Immediate mode rendering + GFX_API void ImmediateVertex( float x, float y, float z ) { } + GFX_API void ImmediateNormal( float x, float y, float z ) { } + GFX_API void ImmediateColor( float r, float g, float b, float a ) { } + GFX_API void ImmediateTexCoordAll( float x, float y, float z ) { } + GFX_API void ImmediateTexCoord( int unit, float x, float y, float z ) { } + GFX_API void ImmediateBegin( GfxPrimitiveType type ) { } + GFX_API void ImmediateEnd() { } + + GFX_API bool CaptureScreenshot( int left, int bottom, int width, int height, UInt8* rgba32 ); + GFX_API bool ReadbackImage( ImageReference& image, int left, int bottom, int width, int height, int destX, int destY ); + GFX_API void GrabIntoRenderTexture( RenderSurfaceHandle rs, RenderSurfaceHandle rd, int x, int y, int width, int height ) { } + + GFX_API void BeforeDrawCall( bool immediateMode ) { } + + GFX_API void SetBlendState(const DeviceBlendState* state, float alphaRef) {} + GFX_API void SetRasterState(const DeviceRasterState* state) {} + GFX_API void SetDepthState(const DeviceDepthState* state) {} + GFX_API void SetStencilState(const DeviceStencilState* state, int stencilRef) {}; + GFX_API void SetSRGBWrite (const bool) {}; + GFX_API bool GetSRGBWrite () {return false;}; + + GFX_API DeviceBlendState* CreateBlendState(const GfxBlendState& state); + GFX_API DeviceDepthState* CreateDepthState(const GfxDepthState& state); + GFX_API DeviceStencilState* CreateStencilState(const GfxStencilState& state); + GFX_API DeviceRasterState* CreateRasterState(const GfxRasterState& state); + + GFX_API bool IsPositionRequiredForTexGen (int texStageIndex) const { return false; } + GFX_API bool IsNormalRequiredForTexGen (int texStageIndex) const { return false; } + GFX_API bool IsPositionRequiredForTexGen() const { return false; } + GFX_API bool IsNormalRequiredForTexGen() const { return false; } + + GFX_API int GetCurrentTargetWidth() const { return 0; } + GFX_API int GetCurrentTargetHeight() const { return 0; } + GFX_API void SetCurrentTargetSize(int width, int height) { } + + #if ENABLE_PROFILER + GFX_API GfxTimerQuery* CreateTimerQuery() { return NULL; } + GFX_API void DeleteTimerQuery(GfxTimerQuery* query) {} + GFX_API void BeginTimerQueries() {} + GFX_API void EndTimerQueries() {} + #endif + #if UNITY_EDITOR + GFX_API void SetAntiAliasFlag( bool aa ) { } + GFX_API void DrawUserPrimitives( GfxPrimitiveType type, int vertexCount, UInt32 vertexChannels, const void* data, int stride ) { } + GFX_API int GetCurrentTargetAA() const { return 0; } + GFX_API GfxDeviceWindow* CreateGfxWindow( HWND window, int width, int height, DepthBufferFormat depthFormat, int antiAlias ) ; + #endif + #if GFX_USES_VIEWPORT_OFFSET + GFX_API void SetViewportOffset( float x, float y ){ } + GFX_API void GetViewportOffset( float &x, float &y ) const{ x = y = 0; } + #endif + +private: + DynamicVBO *dynamicVBO; +}; diff --git a/Runtime/GfxDevice/null/GfxNullVBO.cpp b/Runtime/GfxDevice/null/GfxNullVBO.cpp new file mode 100644 index 0000000..b624160 --- /dev/null +++ b/Runtime/GfxDevice/null/GfxNullVBO.cpp @@ -0,0 +1,107 @@ +#include "UnityPrefix.h" +#include "Runtime/Shaders/VBO.h" +#include "GfxNullVBO.h" +#include "Runtime/GfxDevice/GfxDevice.h" + + + +void GfxNullVBO::UpdateVertexData( const VertexBufferData& buffer ) +{ + BufferAccessibleVertexData(buffer); + } + +void GfxNullVBO::UpdateIndexData (const IndexBufferData& buffer) +{ +} + +void GfxNullVBO::DrawVBO (const ChannelAssigns& channels, UInt32 firstIndexByte, UInt32 indexCount, GfxPrimitiveType topology, UInt32 firstVertex, UInt32 vertexCount ) +{ +} +#if GFX_ENABLE_DRAW_CALL_BATCHING + void GfxNullVBO::DrawCustomIndexed( const ChannelAssigns& channels, void* indices, UInt32 indexCount, + GfxPrimitiveType topology, UInt32 vertexRangeBegin, UInt32 vertexRangeEnd, UInt32 drawVertexCount ) + { + } +#endif + + +bool GfxDynamicNullVBO::GetChunk( UInt32 shaderChannelMask, UInt32 maxVertices, UInt32 maxIndices, RenderMode renderMode, void** outVB, void** outIB ) +{ + AssertIf(this->m_LendedChunk); + AssertIf((maxVertices >= 65536) || (maxIndices >= (65536 * 3))); + bool indexed = IsIndexed(renderMode); + DebugAssertIf(indexed && (outIB == NULL)); + DebugAssertIf(!indexed && ((maxIndices != 0) || (outIB != NULL))); + + this->m_LendedChunk = true; + this->m_LastChunkShaderChannelMask = shaderChannelMask; + this->m_LastRenderMode = renderMode; + + if (maxVertices == 0) + { + maxVertices = 8; + } + + this->m_LastChunkStride = 0; + + for (int i = 0; i < kShaderChannelCount; ++i) + { + if (shaderChannelMask & (1 << i)) + { + this->m_LastChunkStride += GfxNullVBO::GetDefaultChannelByteSize(i); + } + } + + // + + DebugAssertIf(NULL == outVB); + + UInt32 vbCapacity = (maxVertices * this->m_LastChunkStride); + + if (vbCapacity > this->vertexBufferSize) + { + delete[] this->vertexBuffer; + this->vertexBuffer = new UInt8[vbCapacity]; + this->vertexBufferSize = vbCapacity; + } + + *outVB = this->vertexBuffer; + + // + + if (maxIndices && indexed) + { + UInt32 ibCapacity = maxIndices * kVBOIndexSize; + + if (ibCapacity > this->indexBufferSize) + { + delete[] this->indexBuffer; + this->indexBuffer = new UInt8[ibCapacity]; + this->indexBufferSize = ibCapacity; + } + + *outIB = this->indexBuffer; + } + + // + + return true; +} + +void GfxDynamicNullVBO::ReleaseChunk( UInt32 actualVertices, UInt32 actualIndices ) +{ + AssertIf(!m_LendedChunk); + this->m_LendedChunk = false; + + this->m_LastChunkVertices = actualVertices; + this->m_LastChunkIndices = actualIndices; + + if (!actualVertices || (IsIndexed(m_LastRenderMode) && !actualIndices)) + { + this->m_LastChunkShaderChannelMask = 0; + } +} + +void GfxDynamicNullVBO::DrawChunk (const ChannelAssigns& channels) +{ +} diff --git a/Runtime/GfxDevice/null/GfxNullVBO.h b/Runtime/GfxDevice/null/GfxNullVBO.h new file mode 100644 index 0000000..ce4d0fa --- /dev/null +++ b/Runtime/GfxDevice/null/GfxNullVBO.h @@ -0,0 +1,55 @@ +#pragma once + +#include "Runtime/Shaders/BufferedVBO.h" + + +class GfxNullVBO : public BufferedVBO +{ +public: + inline GfxNullVBO(void) {} + virtual ~GfxNullVBO(void) {} + + virtual void UpdateVertexData( const VertexBufferData& buffer ); + virtual void UpdateIndexData (const IndexBufferData& buffer); + virtual void DrawVBO (const ChannelAssigns& channels, UInt32 firstIndexByte, UInt32 indexCount, GfxPrimitiveType topology, UInt32 firstVertex, UInt32 vertexCount ); + #if GFX_ENABLE_DRAW_CALL_BATCHING + virtual void DrawCustomIndexed( const ChannelAssigns& channels, void* indices, UInt32 indexCount, + GfxPrimitiveType topology, UInt32 vertexRangeBegin, UInt32 vertexRangeEnd, UInt32 drawVertexCount ); + #endif + + virtual bool IsVertexBufferLost() const { return false; } + + virtual int GetRuntimeMemorySize() const { return 0; } +}; + + + +class GfxDynamicNullVBO : + public DynamicVBO +{ +private: + UInt8 *vertexBuffer; + UInt32 vertexBufferSize; + UInt8 *indexBuffer; + UInt32 indexBufferSize; + +public: + inline GfxDynamicNullVBO(void) : + vertexBuffer(NULL), + vertexBufferSize(0), + indexBuffer(NULL), + indexBufferSize(0) + { + } + + virtual ~GfxDynamicNullVBO(void) + { + delete[] this->vertexBuffer; + delete[] this->indexBuffer; + } + + virtual bool GetChunk( UInt32 shaderChannelMask, UInt32 maxVertices, UInt32 maxIndices, RenderMode renderMode, void** outVB, void** outIB ); + virtual void ReleaseChunk( UInt32 actualVertices, UInt32 actualIndices ); + virtual void DrawChunk (const ChannelAssigns& channels); + +};
\ No newline at end of file |