1// 2// Copyright (c) 2014-2015 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 dest[x * 4 + 0] = source[x * 3 + 0]; 85 dest[x * 4 + 1] = source[x * 3 + 1]; 86 dest[x * 4 + 2] = source[x * 3 + 2]; 87 dest[x * 4 + 3] = fourthValue; 88 } 89 } 90 } 91} 92 93template <size_t componentCount> 94inline void Load32FTo16F(size_t width, size_t height, size_t depth, 95 const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, 96 uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) 97{ 98 const size_t elementWidth = componentCount * width; 99 100 for (size_t z = 0; z < depth; z++) 101 { 102 for (size_t y = 0; y < height; y++) 103 { 104 const float *source = priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); 105 uint16_t *dest = priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); 106 107 for (size_t x = 0; x < elementWidth; x++) 108 { 109 dest[x] = gl::float32ToFloat16(source[x]); 110 } 111 } 112 } 113} 114 115template <size_t blockWidth, size_t blockHeight, size_t blockSize> 116inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, 117 const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, 118 uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) 119{ 120 const size_t columns = (width + (blockWidth - 1)) / blockWidth; 121 const size_t rows = (height + (blockHeight - 1)) / blockHeight; 122 123 for (size_t z = 0; z < depth; ++z) 124 { 125 for (size_t y = 0; y < rows; ++y) 126 { 127 const uint8_t *source = priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); 128 uint8_t *dest = priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); 129 memcpy(dest, source, columns * blockSize); 130 } 131 } 132} 133 134template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits> 135inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, 136 uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) 137{ 138 type writeValues[4] = 139 { 140 gl::bitCast<type>(firstBits), 141 gl::bitCast<type>(secondBits), 142 gl::bitCast<type>(thirdBits), 143 gl::bitCast<type>(fourthBits), 144 }; 145 146 for (size_t z = 0; z < depth; z++) 147 { 148 for (size_t y = 0; y < height; y++) 149 { 150 type *destRow = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); 151 for (size_t x = 0; x < width; x++) 152 { 153 type* destPixel = destRow + x * 4; 154 155 // This could potentially be optimized by generating an entire row of initialization 156 // data and copying row by row instead of pixel by pixel. 157 memcpy(destPixel, writeValues, sizeof(type) * 4); 158 } 159 } 160 } 161} 162 163} // namespace angle 164