// // Copyright 2019 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #include "renderBuffer.h" #include "pxr/base/gf/half.h" PXR_NAMESPACE_OPEN_SCOPE HdxPrmanRenderBuffer::HdxPrmanRenderBuffer(SdfPath const& id) : HdRenderBuffer(id) , _width(0) , _height(0) , _format(HdFormatInvalid) , _buffer() , _mappers(0) , _converged(false) { } HdxPrmanRenderBuffer::~HdxPrmanRenderBuffer() { } void HdxPrmanRenderBuffer::_Deallocate() { // If the buffer is mapped while we're doing this, there's not a great // recovery path... TF_VERIFY(!IsMapped()); _width = 0; _height = 0; _format = HdFormatInvalid; _buffer.resize(0); _mappers.store(0); _converged.store(false); } /*static*/ size_t HdxPrmanRenderBuffer::_GetBufferSize(GfVec2i const &dims, HdFormat format) { return dims[0] * dims[1] * HdDataSizeOfFormat(format); } /*virtual*/ bool HdxPrmanRenderBuffer::Allocate(GfVec3i const& dimensions, HdFormat format, bool multiSampled) { _Deallocate(); if (dimensions[2] != 1) { TF_WARN("Render buffer allocated with dims <%d, %d, %d> and" " format %s; depth must be 1!", dimensions[0], dimensions[1], dimensions[2], TfEnum::GetName(format).c_str()); return false; } _width = dimensions[0]; _height = dimensions[1]; _format = format; _buffer.resize(_GetBufferSize(GfVec2i(_width, _height), format)); return true; } template static void _ConvertPixel(HdFormat dstFormat, uint8_t *dst, HdFormat srcFormat, uint8_t const *src) { HdFormat srcComponentFormat = HdGetComponentFormat(srcFormat); HdFormat dstComponentFormat = HdGetComponentFormat(dstFormat); size_t srcComponentCount = HdGetComponentCount(srcFormat); size_t dstComponentCount = HdGetComponentCount(dstFormat); for (size_t c = 0; c < dstComponentCount; ++c) { T readValue = 0; if (c < srcComponentCount) { if (srcComponentFormat == HdFormatInt32) { readValue = ((int32_t*)src)[c]; } else if (srcComponentFormat == HdFormatFloat16) { GfHalf half; half.setBits(((uint16_t*)src)[c]); readValue = static_cast(half); } else if (srcComponentFormat == HdFormatFloat32) { readValue = ((float*)src)[c]; } else if (srcComponentFormat == HdFormatUNorm8) { readValue = ((uint8_t*)src)[c] / 255.0f; } else if (srcComponentFormat == HdFormatSNorm8) { readValue = ((int8_t*)src)[c] / 127.0f; } } if (dstComponentFormat == HdFormatInt32) { ((int32_t*)dst)[c] = readValue; } else if (dstComponentFormat == HdFormatFloat16) { ((uint16_t*)dst)[c] = GfHalf(float(readValue)).bits(); } else if (dstComponentFormat == HdFormatFloat32) { ((float*)dst)[c] = readValue; } else if (dstComponentFormat == HdFormatUNorm8) { if (readValue < 0.0f) { ((uint8_t*)dst)[c] = 0; } else if (readValue > 1.0f) { ((uint8_t*)dst)[c] = 255; } else { ((uint8_t*)dst)[c] = uint8_t(readValue *255.0f); } } else if (dstComponentFormat == HdFormatSNorm8) { if (readValue < -1.0f) { ((int8_t*)dst)[c] = -127; } else if (readValue > 1.0f) { ((int8_t*)dst)[c] = 127; } else { ((int8_t*)dst)[c] = int8_t(readValue * 127.0f); } } } } void HdxPrmanRenderBuffer::Blit(HdFormat format, int width, int height, uint8_t const* data) { // Note: use width (not _width) when indexing into source if (width == 0 || height == 0) { // Nothing to copy from, set to zero std::fill(_buffer.begin(), _buffer.end(), 0); } else if (_format == format) { size_t pixelSize = HdDataSizeOfFormat(_format); if (static_cast(width) == _width && static_cast(height) == _height) { // Awesome! Blit line by line. for (unsigned int j = 0; j < _height; ++j) { memcpy(&_buffer[(j * _width) * pixelSize], &data[(j * width) * pixelSize], _width * pixelSize); } } else { // Ok... Blit pixel by pixel, with nearest point sampling. float scalei = width/float(_width); float scalej = height/float(_height); for (unsigned int j = 0; j < _height; ++j) { for (unsigned int i = 0; i < _width; ++i) { unsigned int ii = scalei * i; unsigned int jj = scalej * j; memcpy(&_buffer[(j * _width + i) * pixelSize], &data[(jj * width + ii) * pixelSize], pixelSize); } } } } else { // D'oh. Convert pixel by pixel, with nearest point sampling. // If src and dst are both int-based, don't round trip to float. bool convertAsInt = (HdGetComponentFormat(format) == HdFormatInt32) && (HdGetComponentFormat(_format) == HdFormatInt32); size_t srcPixelSize = HdDataSizeOfFormat(format); size_t dstPixelSize = HdDataSizeOfFormat(_format); float scalei = width/float(_width); float scalej = height/float(_height); for (unsigned int j = 0; j < _height; ++j) { for (unsigned int i = 0; i < _width; ++i) { unsigned int ii = scalei * i; unsigned int jj = scalej * j; if (convertAsInt) { _ConvertPixel( _format, static_cast( &_buffer[(j * _width + i) * dstPixelSize]), format, &data[(jj * width + ii) * srcPixelSize]); } else { _ConvertPixel( _format, static_cast( &_buffer[(j * _width + i) * dstPixelSize]), format, &data[(jj * width + ii) * srcPixelSize]); } } } } } PXR_NAMESPACE_CLOSE_SCOPE