1// 2// Copyright 2014 The ANGLE Project Authors. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6 7#include "common/mathutil.h" 8 9#include <string.h> 10 11namespace angle 12{ 13 14namespace priv 15{ 16 17template <typename T> 18inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) 19{ 20 return reinterpret_cast<T*>(data + (y * rowPitch) + (z * depthPitch)); 21} 22 23template <typename T> 24inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) 25{ 26 return reinterpret_cast<const T*>(data + (y * rowPitch) + (z * depthPitch)); 27} 28 29} // namespace priv 30 31template <typename type, size_t componentCount> 32inline void LoadToNative(size_t width, size_t height, size_t depth, 33 const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, 34 uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) 35{ 36 const size_t rowSize = width * sizeof(type) * componentCount; 37 const size_t layerSize = rowSize * height; 38 const size_t imageSize = layerSize * depth; 39 40 if (layerSize == inputDepthPitch && layerSize == outputDepthPitch) 41 { 42 ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch); 43 memcpy(output, input, imageSize); 44 } 45 else if (rowSize == inputRowPitch && rowSize == outputRowPitch) 46 { 47 for (size_t z = 0; z < depth; z++) 48 { 49 const type *source = priv::OffsetDataPointer<type>(input, 0, z, inputRowPitch, inputDepthPitch); 50 type *dest = priv::OffsetDataPointer<type>(output, 0, z, outputRowPitch, outputDepthPitch); 51 52 memcpy(dest, source, layerSize); 53 } 54 } 55 else 56 { 57 for (size_t z = 0; z < depth; z++) 58 { 59 for (size_t y = 0; y < height; y++) 60 { 61 const type *source = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch); 62 type *dest = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); 63 memcpy(dest, source, width * sizeof(type) * componentCount); 64 } 65 } 66 } 67} 68 69template <typename type, uint32_t fourthComponentBits> 70inline void LoadToNative3To4(size_t width, size_t height, size_t depth, 71 const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, 72 uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) 73{ 74 const type fourthValue = gl::bitCast<type>(fourthComponentBits); 75 76 for (size_t z = 0; z < depth; z++) 77 { 78 for (size_t y = 0; y < height; y++) 79 { 80 const type *source = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch); 81 type *dest = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); 82 for (size_t x = 0; x < width; x++) 83 { 84 memcpy(&dest[x * 4], &source[x * 3], sizeof(type) * 3); 85 dest[x * 4 + 3] = fourthValue; 86 } 87 } 88 } 89} 90 91template <size_t componentCount> 92inline void Load32FTo16F(size_t width, size_t height, size_t depth, 93 const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, 94 uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) 95{ 96 const size_t elementWidth = componentCount * width; 97 98 for (size_t z = 0; z < depth; z++) 99 { 100 for (size_t y = 0; y < height; y++) 101 { 102 const float *source = priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); 103 uint16_t *dest = priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); 104 105 for (size_t x = 0; x < elementWidth; x++) 106 { 107 dest[x] = gl::float32ToFloat16(source[x]); 108 } 109 } 110 } 111} 112 113template <size_t blockWidth, size_t blockHeight, size_t blockDepth, size_t blockSize> 114inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, 115 const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, 116 uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) 117{ 118 const size_t columns = (width + (blockWidth - 1)) / blockWidth; 119 const size_t rows = (height + (blockHeight - 1)) / blockHeight; 120 const size_t layers = (depth + (blockDepth - 1)) / blockDepth; 121 122 for (size_t z = 0; z < layers; ++z) 123 { 124 for (size_t y = 0; y < rows; ++y) 125 { 126 const uint8_t *source = priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); 127 uint8_t *dest = priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); 128 memcpy(dest, source, columns * blockSize); 129 } 130 } 131} 132 133template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits> 134inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, 135 uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) 136{ 137 type writeValues[4] = 138 { 139 gl::bitCast<type>(firstBits), 140 gl::bitCast<type>(secondBits), 141 gl::bitCast<type>(thirdBits), 142 gl::bitCast<type>(fourthBits), 143 }; 144 145 for (size_t z = 0; z < depth; z++) 146 { 147 for (size_t y = 0; y < height; y++) 148 { 149 type *destRow = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); 150 for (size_t x = 0; x < width; x++) 151 { 152 type* destPixel = destRow + x * 4; 153 154 // This could potentially be optimized by generating an entire row of initialization 155 // data and copying row by row instead of pixel by pixel. 156 memcpy(destPixel, writeValues, sizeof(type) * 4); 157 } 158 } 159 } 160} 161 162} // namespace angle 163