diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-05-03 18:42:13 -0400 |
|---|---|---|
| committer | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-05-03 15:42:13 -0700 |
| commit | f8472940229e8582ec9f941069fc9576bd09b94c (patch) | |
| tree | 9b387a65abc42094e7a1e0687b793cb0fc5c5eaa /tools/render-test/surface.cpp | |
| parent | c216f00f1eaff368229cb8430422972fcac801b7 (diff) | |
Added Surface type - as a simple value type to hold a 2d collection of pixels. (#548)
Added PngSerializeUtil allows currently for just writing Surface of RGBA format.
Removes dependency on stbi_image except for in PngSerializeUtil.
Removed use of gWindowWidth/Height globals - pass the height into initialize or Renderer.
Diffstat (limited to 'tools/render-test/surface.cpp')
| -rw-r--r-- | tools/render-test/surface.cpp | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/tools/render-test/surface.cpp b/tools/render-test/surface.cpp new file mode 100644 index 000000000..3f96052ce --- /dev/null +++ b/tools/render-test/surface.cpp @@ -0,0 +1,191 @@ +// surface.cpp +#include "surface.h" + +#include <stdlib.h> +#include <stdio.h> + +#include "../../source/core/list.h" + +namespace renderer_test { +using namespace Slang; + +class MallocSurfaceAllocator: public SurfaceAllocator +{ + public: + + virtual Slang::Result allocate(int width, int height, Format format, int alignment, Surface& surface) override; + virtual void deallocate(Surface& surface) override; +}; + +static MallocSurfaceAllocator s_mallocSurfaceAllocator; + +/// Get the malloc allocator +/* static */SurfaceAllocator* SurfaceAllocator::getMallocAllocator() +{ + return &s_mallocSurfaceAllocator; +} + +Slang::Result MallocSurfaceAllocator::allocate(int width, int height, Format format, int alignment, Surface& surface) +{ + assert(surface.m_data == nullptr); + + // Calculate row size + + const int rowSizeInBytes = Surface::calcRowSize(format, width); + const int numRows = Surface::calcNumRows(format, height); + + alignment = (alignment <= 0) ? int(sizeof(void*)) : alignment; + // It must be a power of 2 + assert( ((alignment - 1) & alignment) == 0); + + // Align rowSize + const int alignedRowSizeInBytes = (rowSizeInBytes + alignment - 1) & -alignment; + + size_t totalSize = numRows * alignedRowSizeInBytes; + + uint8_t* data = (uint8_t*)::malloc(totalSize); + if (!data) + { + return SLANG_E_MEM_OUT_OF_MEMORY; + } + + surface.m_data = data; + surface.m_width = width; + surface.m_height = height; + surface.m_format = format; + surface.m_numRows = numRows; + surface.m_rowStrideInBytes = alignedRowSizeInBytes; + + surface.m_allocator = this; + return SLANG_OK; +} + +void MallocSurfaceAllocator::deallocate(Surface& surface) +{ + assert(surface.m_data); + // Make sure it's not an inverted, cos otherwise m_data is not the start address + assert(surface.m_rowStrideInBytes > 0); + ::free(surface.m_data); +} + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Surface !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +/* static */int Surface::calcRowSize(Format format, int width) +{ + size_t pixelSize = RendererUtil::getFormatSize(format); + if (pixelSize == 0) + { + return 0; + } + return int(pixelSize * width); +} + +/* static */int Surface::calcNumRows(Format format, int height) +{ + // Don't have any compressed types, so number of rows is same as the height + return height; +} + +void Surface::init() +{ + m_width = 0; + m_height = 0; + m_format = Format::Unknown; + m_data = nullptr; + m_numRows = 0; + m_rowStrideInBytes = 0; + // NOTE! does not clear the allocator. + // If called with an allocation memory will leak! +} + +Surface::~Surface() +{ + if (m_data && m_allocator) + { + m_allocator->deallocate(*this); + } +} + +void Surface::deallocate() +{ + if (m_data && m_allocator) + { + m_allocator->deallocate(*this); + init(); + } +} + +Result Surface::allocate(int width, int height, Format format, int alignment, SurfaceAllocator* allocator) +{ + deallocate(); + allocator = allocator ? allocator : m_allocator; + if (!allocator) + { + // An allocator needs to be set on the surface, or one passed in. + return SLANG_FAIL; + } + return allocator->allocate(width, height, format, alignment, *this); +} + +void Surface::setUnowned(int width, int height, Format format, int strideInBytes, void* data) +{ + deallocate(); + + // This is unowned + m_allocator = nullptr; + + m_width = width; + m_height = height; + m_format = format; + m_rowStrideInBytes = strideInBytes; + m_data = (uint8_t*)data; + + m_numRows = Surface::calcNumRows(format, height); + + const int rowSizeInBytes = Surface::calcRowSize(format, width); + assert((strideInBytes > 0 && rowSizeInBytes <= strideInBytes) || (strideInBytes < 0 && rowSizeInBytes <= -strideInBytes)); +} + +void Surface::zeroContents() +{ + const int rowSizeInBytes = Surface::calcRowSize(m_format, m_width); + + const int stride = m_rowStrideInBytes; + uint8_t* dst = m_data; + + for (int i = 0; i < m_numRows; i++, dst += stride) + { + ::memset(dst, 0, rowSizeInBytes); + } +} + +void Surface::flipInplaceVertically() +{ + // Can only flip when m_height matches number of rows + assert(m_numRows == m_height); + + const int rowSizeInBytes = Surface::calcRowSize(m_format, m_width); + if (rowSizeInBytes <= 0 || m_numRows <= 1) + { + return; + } + + uint8_t* top = m_data; + uint8_t* bottom = m_data + (m_numRows - 1) * m_rowStrideInBytes; + + List<uint8_t> bufferList; + bufferList.SetSize(rowSizeInBytes); + uint8_t* buffer = bufferList.Buffer(); + + const int stride = m_rowStrideInBytes; + + const int num = m_height >> 1; + for (int i = 0; i < num; ++i, top += stride, bottom -= stride) + { + ::memcpy(buffer, top, rowSizeInBytes); + ::memcpy(top, bottom, rowSizeInBytes); + ::memcpy(bottom, buffer, rowSizeInBytes); + } +} + +} // renderer_test |
