Hash :
7619f8a0
Author :
Date :
2025-06-11T00:44:36
Fast copy R8G8B8A8_UNORM / R8G8B8A8_UNORM_SRGB for readPixels Support FastCopyFunction on R8G8B8A8_UNORM and R8G8B8A8_UNORM_SRGB. Copying src pixels to dest directly is more performant than converting UNORM to GLfloat. Bug: b/429541195 Tests: dEQP-GLES31.functional.srgb_texture_decode.skip_decode* Change-Id: If9a3d75dbf7b9fd286a61b144ed607144c833740 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6704713 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
//
// Copyright 2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifdef UNSAFE_BUFFERS_BUILD
# pragma allow_unsafe_buffers
#endif
// copyimage.cpp: Defines image copying functions
#include "image_util/copyimage.h"
namespace angle
{
namespace
{
inline uint32_t SwizzleBGRAToRGBA(uint32_t argb)
{
return ((argb & 0x000000FF) << 16) | // Move BGRA blue to RGBA blue
((argb & 0x00FF0000) >> 16) | // Move BGRA red to RGBA red
((argb & 0xFF00FF00)); // Keep alpha and green
}
void CopyBGRA8ToRGBA8Fast(const uint8_t *source,
int srcYAxisPitch,
uint8_t *dest,
int destYAxisPitch,
int destWidth,
int destHeight)
{
for (int y = 0; y < destHeight; ++y)
{
const uint32_t *src32 = reinterpret_cast<const uint32_t *>(source + y * srcYAxisPitch);
uint32_t *dest32 = reinterpret_cast<uint32_t *>(dest + y * destYAxisPitch);
const uint32_t *end32 = src32 + destWidth;
while (src32 != end32)
{
*dest32++ = SwizzleBGRAToRGBA(*src32++);
}
}
}
void CopyRGBA8ToRGBA8Fast(const uint8_t *source,
int srcYAxisPitch,
uint8_t *dest,
int destYAxisPitch,
int destWidth,
int destHeight)
{
// If Y axis pitch is packed and the source is also packed and stored contiguously, copy the
// whole source to the dest in a single memcpy operation.
if (destYAxisPitch == destWidth * 4 && srcYAxisPitch == destWidth * 4)
{
size_t totalSize = destHeight * destWidth * 4;
memcpy(dest, source, totalSize);
return;
}
// If X axis pitch is 4 bytes but Y axis pitch is not packed, copy the source to dest line by
// line.
for (int y = 0; y < destHeight; ++y)
{
const uint8_t *src = source + y * srcYAxisPitch;
uint8_t *dst = dest + y * destYAxisPitch;
memcpy(dst, src, destWidth * 4);
}
}
} // namespace
void CopyBGRA8ToRGBA8(const uint8_t *source,
int srcXAxisPitch,
int srcYAxisPitch,
uint8_t *dest,
int destXAxisPitch,
int destYAxisPitch,
int destWidth,
int destHeight)
{
if (srcXAxisPitch == 4 && destXAxisPitch == 4)
{
CopyBGRA8ToRGBA8Fast(source, srcYAxisPitch, dest, destYAxisPitch, destWidth, destHeight);
return;
}
for (int y = 0; y < destHeight; ++y)
{
uint8_t *dst = dest + y * destYAxisPitch;
const uint8_t *src = source + y * srcYAxisPitch;
const uint8_t *end = src + destWidth * srcXAxisPitch;
while (src != end)
{
*reinterpret_cast<uint32_t *>(dst) =
SwizzleBGRAToRGBA(*reinterpret_cast<const uint32_t *>(src));
src += srcXAxisPitch;
dst += destXAxisPitch;
}
}
}
void CopyRGBA8ToRGBA8(const uint8_t *source,
int srcXAxisPitch,
int srcYAxisPitch,
uint8_t *dest,
int destXAxisPitch,
int destYAxisPitch,
int destWidth,
int destHeight)
{
if (srcXAxisPitch == 4 && destXAxisPitch == 4)
{
CopyRGBA8ToRGBA8Fast(source, srcYAxisPitch, dest, destYAxisPitch, destWidth, destHeight);
return;
}
for (int y = 0; y < destHeight; ++y)
{
uint8_t *dst = dest + y * destYAxisPitch;
const uint8_t *src = source + y * srcYAxisPitch;
const uint8_t *end = src + destWidth * srcXAxisPitch;
while (src != end)
{
*reinterpret_cast<uint32_t *>(dst) = *reinterpret_cast<const uint32_t *>(src);
src += srcXAxisPitch;
dst += destXAxisPitch;
}
}
}
} // namespace angle