blob: ef5e93b90b7f96ddb7d59c6ed3c3b4f90bb65757 [file] [log] [blame]
// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "Image.hpp"
#include "../libEGL/Context.hpp"
#include "../libEGL/Texture.hpp"
#include "../common/debug.h"
#include "Common/Math.hpp"
#include "Common/Thread.hpp"
#include <GLES3/gl3.h>
#include <string.h>
namespace
{
int getNumBlocks(int w, int h, int blockSizeX, int blockSizeY)
{
return ((w + blockSizeX - 1) / blockSizeX) * ((h + blockSizeY - 1) / blockSizeY);
}
enum DataType
{
Bytes_1,
Bytes_2,
Bytes_4,
Bytes_8,
Bytes_16,
ByteRGB,
UByteRGB,
ShortRGB,
UShortRGB,
IntRGB,
UIntRGB,
FloatRGB,
HalfFloatRGB,
RGBA4444,
RGBA5551,
R11G11B10F,
RGB9E5,
D16,
D24,
D32,
D32F,
D32FS8,
S8,
S24_8,
};
template<DataType dataType>
void LoadImageRow(const unsigned char *source, unsigned char *dest, GLsizei width)
{
UNIMPLEMENTED();
}
template<>
void LoadImageRow<Bytes_1>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
memcpy(dest, source, width);
}
template<>
void LoadImageRow<Bytes_2>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
memcpy(dest, source, width * 2);
}
template<>
void LoadImageRow<Bytes_4>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
memcpy(dest, source, width * 4);
}
template<>
void LoadImageRow<Bytes_8>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
memcpy(dest, source, width * 8);
}
template<>
void LoadImageRow<Bytes_16>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
memcpy(dest, source, width * 16);
}
template<>
void LoadImageRow<ByteRGB>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
unsigned char *destB = dest;
for(int x = 0; x < width; x++)
{
destB[4 * x + 0] = source[x * 3 + 0];
destB[4 * x + 1] = source[x * 3 + 1];
destB[4 * x + 2] = source[x * 3 + 2];
destB[4 * x + 3] = 0x7F;
}
}
template<>
void LoadImageRow<UByteRGB>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
unsigned char *destB = dest;
for(int x = 0; x < width; x++)
{
destB[4 * x + 0] = source[x * 3 + 0];
destB[4 * x + 1] = source[x * 3 + 1];
destB[4 * x + 2] = source[x * 3 + 2];
destB[4 * x + 3] = 0xFF;
}
}
template<>
void LoadImageRow<ShortRGB>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned short *sourceS = reinterpret_cast<const unsigned short*>(source);
unsigned short *destS = reinterpret_cast<unsigned short*>(dest);
for(int x = 0; x < width; x++)
{
destS[4 * x + 0] = sourceS[x * 3 + 0];
destS[4 * x + 1] = sourceS[x * 3 + 1];
destS[4 * x + 2] = sourceS[x * 3 + 2];
destS[4 * x + 3] = 0x7FFF;
}
}
template<>
void LoadImageRow<UShortRGB>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned short *sourceS = reinterpret_cast<const unsigned short*>(source);
unsigned short *destS = reinterpret_cast<unsigned short*>(dest);
for(int x = 0; x < width; x++)
{
destS[4 * x + 0] = sourceS[x * 3 + 0];
destS[4 * x + 1] = sourceS[x * 3 + 1];
destS[4 * x + 2] = sourceS[x * 3 + 2];
destS[4 * x + 3] = 0xFFFF;
}
}
template<>
void LoadImageRow<IntRGB>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned int *sourceI = reinterpret_cast<const unsigned int*>(source);
unsigned int *destI = reinterpret_cast<unsigned int*>(dest);
for(int x = 0; x < width; x++)
{
destI[4 * x + 0] = sourceI[x * 3 + 0];
destI[4 * x + 1] = sourceI[x * 3 + 1];
destI[4 * x + 2] = sourceI[x * 3 + 2];
destI[4 * x + 3] = 0x7FFFFFFF;
}
}
template<>
void LoadImageRow<UIntRGB>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned int *sourceI = reinterpret_cast<const unsigned int*>(source);
unsigned int *destI = reinterpret_cast<unsigned int*>(dest);
for(int x = 0; x < width; x++)
{
destI[4 * x + 0] = sourceI[x * 3 + 0];
destI[4 * x + 1] = sourceI[x * 3 + 1];
destI[4 * x + 2] = sourceI[x * 3 + 2];
destI[4 * x + 3] = 0xFFFFFFFF;
}
}
template<>
void LoadImageRow<FloatRGB>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const float *sourceF = reinterpret_cast<const float*>(source);
float *destF = reinterpret_cast<float*>(dest);
for(int x = 0; x < width; x++)
{
destF[4 * x + 0] = sourceF[x * 3 + 0];
destF[4 * x + 1] = sourceF[x * 3 + 1];
destF[4 * x + 2] = sourceF[x * 3 + 2];
destF[4 * x + 3] = 1.0f;
}
}
template<>
void LoadImageRow<HalfFloatRGB>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned short *sourceH = reinterpret_cast<const unsigned short*>(source);
unsigned short *destH = reinterpret_cast<unsigned short*>(dest);
for(int x = 0; x < width; x++)
{
destH[4 * x + 0] = sourceH[x * 3 + 0];
destH[4 * x + 1] = sourceH[x * 3 + 1];
destH[4 * x + 2] = sourceH[x * 3 + 2];
destH[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
}
}
template<>
void LoadImageRow<RGBA4444>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned short *source4444 = reinterpret_cast<const unsigned short*>(source);
unsigned char *dest4444 = dest;
for(int x = 0; x < width; x++)
{
unsigned short rgba = source4444[x];
dest4444[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
dest4444[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
dest4444[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
dest4444[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
}
}
template<>
void LoadImageRow<RGBA5551>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned short *source5551 = reinterpret_cast<const unsigned short*>(source);
unsigned char *dest5551 = dest;
for(int x = 0; x < width; x++)
{
unsigned short rgba = source5551[x];
dest5551[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
dest5551[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
dest5551[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
dest5551[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
}
}
template<>
void LoadImageRow<R11G11B10F>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const sw::R11G11B10F *sourceRGB = reinterpret_cast<const sw::R11G11B10F*>(source);
sw::half *destF = reinterpret_cast<sw::half*>(dest);
for(int x = 0; x < width; x++, sourceRGB++, destF+=4)
{
sourceRGB->toRGB16F(destF);
destF[3] = 1.0f;
}
}
template<>
void LoadImageRow<RGB9E5>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const sw::RGB9E5 *sourceRGB = reinterpret_cast<const sw::RGB9E5*>(source);
sw::half *destF = reinterpret_cast<sw::half*>(dest);
for(int x = 0; x < width; x++, sourceRGB++, destF += 4)
{
sourceRGB->toRGB16F(destF);
destF[3] = 1.0f;
}
}
template<>
void LoadImageRow<D16>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned short *sourceD16 = reinterpret_cast<const unsigned short*>(source);
float *destF = reinterpret_cast<float*>(dest);
for(int x = 0; x < width; x++)
{
destF[x] = (float)sourceD16[x] / 0xFFFF;
}
}
template<>
void LoadImageRow<D24>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned int *sourceD24 = reinterpret_cast<const unsigned int*>(source);
float *destF = reinterpret_cast<float*>(dest);
for(int x = 0; x < width; x++)
{
destF[x] = (float)(sourceD24[x] & 0xFFFFFF00) / 0xFFFFFF00;
}
}
template<>
void LoadImageRow<D32>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned int *sourceD32 = reinterpret_cast<const unsigned int*>(source);
float *destF = reinterpret_cast<float*>(dest);
for(int x = 0; x < width; x++)
{
destF[x] = (float)sourceD32[x] / 0xFFFFFFFF;
}
}
template<>
void LoadImageRow<S8>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const unsigned int *sourceI = reinterpret_cast<const unsigned int*>(source);
unsigned char *destI = dest;
for(int x = 0; x < width; x++)
{
destI[x] = static_cast<unsigned char>(sourceI[x] & 0x000000FF); // FIXME: Quad layout
}
}
template<>
void LoadImageRow<D32F>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
const float *sourceF = reinterpret_cast<const float*>(source);
float *destF = reinterpret_cast<float*>(dest);
for(int x = 0; x < width; x++)
{
destF[x] = sw::clamp(sourceF[x], 0.0f, 1.0f);
}
}
template<>
void LoadImageRow<D32FS8>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
struct D32FS8 { float depth32f; unsigned int stencil24_8; };
const D32FS8 *sourceD32FS8 = reinterpret_cast<const D32FS8*>(source);
float *destF = reinterpret_cast<float*>(dest);
for(int x = 0; x < width; x++)
{
destF[x] = sw::clamp(sourceD32FS8[x].depth32f, 0.0f, 1.0f);
}
}
template<>
void LoadImageRow<S24_8>(const unsigned char *source, unsigned char *dest, GLsizei width)
{
struct D32FS8 { float depth32f; unsigned int stencil24_8; };
const D32FS8 *sourceD32FS8 = reinterpret_cast<const D32FS8*>(source);
unsigned char *destI = dest;
for(int x = 0; x < width; x++)
{
destI[x] = static_cast<unsigned char>(sourceD32FS8[x].stencil24_8 & 0x000000FF); // FIXME: Quad layout
}
}
template<DataType dataType>
void LoadImageData(GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, int destPitch, GLsizei destSlice, const void *input, void *buffer)
{
for(int z = 0; z < depth; z++)
{
const unsigned char *inputStart = static_cast<const unsigned char*>(input) + (z * inputPitch * inputHeight);
unsigned char *destStart = static_cast<unsigned char*>(buffer) + (z * destSlice);
for(int y = 0; y < height; y++)
{
const unsigned char *source = inputStart + y * inputPitch;
unsigned char *dest = destStart + y * destPitch;
LoadImageRow<dataType>(source, dest, width);
}
}
}
}
namespace egl
{
sw::Format ConvertFormatType(GLenum format, GLenum type)
{
switch(format)
{
case GL_LUMINANCE:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_L8;
case GL_HALF_FLOAT: return sw::FORMAT_L16F;
case GL_HALF_FLOAT_OES: return sw::FORMAT_L16F;
case GL_FLOAT: return sw::FORMAT_L32F;
default: UNREACHABLE(type);
}
break;
case GL_LUMINANCE8_EXT:
return sw::FORMAT_L8;
case GL_LUMINANCE16F_EXT:
return sw::FORMAT_L16F;
case GL_LUMINANCE32F_EXT:
return sw::FORMAT_L32F;
case GL_LUMINANCE_ALPHA:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_A8L8;
case GL_HALF_FLOAT: return sw::FORMAT_A16L16F;
case GL_HALF_FLOAT_OES: return sw::FORMAT_A16L16F;
case GL_FLOAT: return sw::FORMAT_A32L32F;
default: UNREACHABLE(type);
}
break;
case GL_LUMINANCE8_ALPHA8_EXT:
return sw::FORMAT_A8L8;
case GL_LUMINANCE_ALPHA16F_EXT:
return sw::FORMAT_A16L16F;
case GL_LUMINANCE_ALPHA32F_EXT:
return sw::FORMAT_A32L32F;
case GL_RGBA:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_A8B8G8R8;
case GL_UNSIGNED_SHORT_4_4_4_4: return sw::FORMAT_R4G4B4A4;
case GL_UNSIGNED_SHORT_5_5_5_1: return sw::FORMAT_R5G5B5A1;
case GL_HALF_FLOAT: return sw::FORMAT_A16B16G16R16F;
case GL_HALF_FLOAT_OES: return sw::FORMAT_A16B16G16R16F;
case GL_FLOAT: return sw::FORMAT_A32B32G32R32F;
default: UNREACHABLE(type);
}
break;
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_A8R8G8B8;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return sw::FORMAT_A4R4G4B4;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return sw::FORMAT_A1R5G5B5;
default: UNREACHABLE(type);
}
break;
case GL_RGB:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_B8G8R8;
case GL_UNSIGNED_SHORT_5_6_5: return sw::FORMAT_R5G6B5;
case GL_HALF_FLOAT: return sw::FORMAT_B16G16R16F;
case GL_HALF_FLOAT_OES: return sw::FORMAT_B16G16R16F;
case GL_FLOAT: return sw::FORMAT_B32G32R32F;
default: UNREACHABLE(type);
}
break;
case GL_RG:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_G8R8;
case GL_HALF_FLOAT: return sw::FORMAT_G16R16F;
case GL_HALF_FLOAT_OES: return sw::FORMAT_G16R16F;
case GL_FLOAT: return sw::FORMAT_G32R32F;
default: UNREACHABLE(type);
}
break;
case GL_RED:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_R8;
case GL_HALF_FLOAT: return sw::FORMAT_R16F;
case GL_HALF_FLOAT_OES: return sw::FORMAT_R16F;
case GL_FLOAT: return sw::FORMAT_R32F;
default: UNREACHABLE(type);
}
break;
case GL_ALPHA:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_A8;
case GL_HALF_FLOAT: return sw::FORMAT_A16F;
case GL_HALF_FLOAT_OES: return sw::FORMAT_A16F;
case GL_FLOAT: return sw::FORMAT_A32F;
default: UNREACHABLE(type);
}
break;
case GL_ALPHA8_EXT:
return sw::FORMAT_A8;
case GL_ALPHA16F_EXT:
return sw::FORMAT_A16F;
case GL_ALPHA32F_EXT:
return sw::FORMAT_A32F;
case GL_RED_INTEGER:
switch(type)
{
case GL_INT: return sw::FORMAT_R32I;
case GL_UNSIGNED_INT: return sw::FORMAT_R32UI;
default: UNREACHABLE(type);
}
break;
case GL_RG_INTEGER:
switch(type)
{
case GL_INT: return sw::FORMAT_G32R32I;
case GL_UNSIGNED_INT: return sw::FORMAT_G32R32UI;
default: UNREACHABLE(type);
}
break;
case GL_RGBA_INTEGER:
switch(type)
{
case GL_INT: return sw::FORMAT_A32B32G32R32I;
case GL_UNSIGNED_INT: return sw::FORMAT_A32B32G32R32UI;
case GL_UNSIGNED_INT_2_10_10_10_REV: return sw::FORMAT_A2B10G10R10UI;
default: UNREACHABLE(type);
}
break;
case GL_DEPTH_COMPONENT:
switch(type)
{
case GL_UNSIGNED_SHORT: return sw::FORMAT_D16;
case GL_UNSIGNED_INT_24_8_OES: return sw::FORMAT_D24S8;
case GL_UNSIGNED_INT: return sw::FORMAT_D32;
case GL_FLOAT: return sw::FORMAT_D32F_LOCKABLE;
default: UNREACHABLE(type);
}
break;
default:
UNREACHABLE(format);
}
return sw::FORMAT_NULL;
}
sw::Format SelectInternalFormat(GLenum format, GLenum type)
{
switch(format)
{
case GL_ETC1_RGB8_OES:
return sw::FORMAT_ETC1;
case GL_COMPRESSED_R11_EAC:
return sw::FORMAT_R11_EAC;
case GL_COMPRESSED_SIGNED_R11_EAC:
return sw::FORMAT_SIGNED_R11_EAC;
case GL_COMPRESSED_RG11_EAC:
return sw::FORMAT_RG11_EAC;
case GL_COMPRESSED_SIGNED_RG11_EAC:
return sw::FORMAT_SIGNED_RG11_EAC;
case GL_COMPRESSED_RGB8_ETC2:
return sw::FORMAT_RGB8_ETC2;
case GL_COMPRESSED_SRGB8_ETC2:
return sw::FORMAT_SRGB8_ETC2;
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
return sw::FORMAT_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
return sw::FORMAT_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
case GL_COMPRESSED_RGBA8_ETC2_EAC:
return sw::FORMAT_RGBA8_ETC2_EAC;
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
return sw::FORMAT_SRGB8_ALPHA8_ETC2_EAC;
case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
return sw::FORMAT_RGBA_ASTC_4x4_KHR;
case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
return sw::FORMAT_RGBA_ASTC_5x4_KHR;
case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
return sw::FORMAT_RGBA_ASTC_5x5_KHR;
case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
return sw::FORMAT_RGBA_ASTC_6x5_KHR;
case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
return sw::FORMAT_RGBA_ASTC_6x6_KHR;
case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
return sw::FORMAT_RGBA_ASTC_8x5_KHR;
case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
return sw::FORMAT_RGBA_ASTC_8x6_KHR;
case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
return sw::FORMAT_RGBA_ASTC_8x8_KHR;
case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
return sw::FORMAT_RGBA_ASTC_10x5_KHR;
case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
return sw::FORMAT_RGBA_ASTC_10x6_KHR;
case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
return sw::FORMAT_RGBA_ASTC_10x8_KHR;
case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
return sw::FORMAT_RGBA_ASTC_10x10_KHR;
case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
return sw::FORMAT_RGBA_ASTC_12x10_KHR;
case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
return sw::FORMAT_RGBA_ASTC_12x12_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_6x5_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
return sw::FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return sw::FORMAT_DXT1;
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
return sw::FORMAT_DXT3;
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
return sw::FORMAT_DXT5;
default:
break;
}
switch(type)
{
case GL_FLOAT:
switch(format)
{
case GL_ALPHA:
case GL_ALPHA32F_EXT:
return sw::FORMAT_A32F;
case GL_LUMINANCE:
case GL_LUMINANCE32F_EXT:
return sw::FORMAT_L32F;
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE_ALPHA32F_EXT:
return sw::FORMAT_A32L32F;
case GL_RED:
case GL_R32F:
return sw::FORMAT_R32F;
case GL_RG:
case GL_RG32F:
return sw::FORMAT_G32R32F;
case GL_RGB:
case GL_RGB32F:
return sw::FORMAT_X32B32G32R32F;
case GL_R11F_G11F_B10F:
case GL_RGB9_E5:
return sw::FORMAT_X16B16G16R16F_UNSIGNED;
case GL_RGBA:
case GL_RGBA32F:
return sw::FORMAT_A32B32G32R32F;
case GL_R16F:
return sw::FORMAT_R16F;
case GL_RG16F:
return sw::FORMAT_G16R16F;
case GL_RGB16F:
return sw::FORMAT_X16B16G16R16F;
case GL_RGBA16F:
return sw::FORMAT_A16B16G16R16F;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT32F:
return sw::FORMAT_D32F;
default:
UNREACHABLE(format);
}
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
switch(format)
{
case GL_ALPHA:
case GL_ALPHA16F_EXT:
return sw::FORMAT_A16F;
case GL_LUMINANCE:
case GL_LUMINANCE16F_EXT:
return sw::FORMAT_L16F;
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE_ALPHA16F_EXT:
return sw::FORMAT_A16L16F;
case GL_RED:
case GL_R16F:
return sw::FORMAT_R16F;
case GL_RG:
case GL_RG16F:
return sw::FORMAT_G16R16F;
case GL_RGBA:
case GL_RGBA16F:
return sw::FORMAT_A16B16G16R16F;
case GL_RGB:
case GL_RGB16F:
return sw::FORMAT_X16B16G16R16F;
case GL_R11F_G11F_B10F:
case GL_RGB9_E5:
return sw::FORMAT_X16B16G16R16F_UNSIGNED;
default:
UNREACHABLE(format);
}
case GL_BYTE:
switch(format)
{
case GL_R8_SNORM:
case GL_R8:
case GL_RED:
return sw::FORMAT_R8_SNORM;
case GL_R8I:
case GL_RED_INTEGER:
return sw::FORMAT_R8I;
case GL_RG8_SNORM:
case GL_RG8:
case GL_RG:
return sw::FORMAT_G8R8_SNORM;
case GL_RG8I:
case GL_RG_INTEGER:
return sw::FORMAT_G8R8I;
case GL_RGB8_SNORM:
case GL_RGB8:
case GL_RGB:
return sw::FORMAT_X8B8G8R8_SNORM;
case GL_RGB8I:
case GL_RGB_INTEGER:
return sw::FORMAT_X8B8G8R8I;
case GL_RGBA8_SNORM:
case GL_RGBA8:
case GL_RGBA:
return sw::FORMAT_A8B8G8R8_SNORM;
case GL_RGBA8I:
case GL_RGBA_INTEGER:
return sw::FORMAT_A8B8G8R8I;
default:
UNREACHABLE(format);
}
case GL_UNSIGNED_BYTE:
switch(format)
{
case GL_LUMINANCE:
case GL_LUMINANCE8_EXT:
return sw::FORMAT_L8;
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE8_ALPHA8_EXT:
return sw::FORMAT_A8L8;
case GL_R8_SNORM:
return sw::FORMAT_R8_SNORM;
case GL_R8:
case GL_RED:
return sw::FORMAT_R8;
case GL_R8UI:
case GL_RED_INTEGER:
return sw::FORMAT_R8UI;
case GL_RG8_SNORM:
case GL_RG8:
case GL_RG:
return sw::FORMAT_G8R8;
case GL_RG8UI:
case GL_RG_INTEGER:
return sw::FORMAT_G8R8UI;
case GL_RGB8_SNORM:
case GL_RGB8:
case GL_RGB:
return sw::FORMAT_X8B8G8R8;
case GL_SRGB8:
return sw::FORMAT_SRGB8_X8;
case GL_RGB8UI:
case GL_RGB_INTEGER:
return sw::FORMAT_X8B8G8R8UI;
case GL_RGBA8_SNORM:
case GL_RGBA8:
case GL_RGBA:
return sw::FORMAT_A8B8G8R8;
case GL_SRGB8_ALPHA8:
return sw::FORMAT_SRGB8_A8;
case GL_RGBA8UI:
case GL_RGBA_INTEGER:
return sw::FORMAT_A8B8G8R8UI;
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
return sw::FORMAT_A8R8G8B8;
case GL_ALPHA:
case GL_ALPHA8_EXT:
return sw::FORMAT_A8;
case SW_YV12_BT601:
return sw::FORMAT_YV12_BT601;
case SW_YV12_BT709:
return sw::FORMAT_YV12_BT709;
case SW_YV12_JFIF:
return sw::FORMAT_YV12_JFIF;
default:
UNREACHABLE(format);
}
case GL_SHORT:
switch(format)
{
case GL_R16I:
case GL_RED_INTEGER:
return sw::FORMAT_R16I;
case GL_RG16I:
case GL_RG_INTEGER:
return sw::FORMAT_G16R16I;
case GL_RGB16I:
case GL_RGB_INTEGER:
return sw::FORMAT_X16B16G16R16I;
case GL_RGBA16I:
case GL_RGBA_INTEGER:
return sw::FORMAT_A16B16G16R16I;
default:
UNREACHABLE(format);
}
case GL_UNSIGNED_SHORT:
switch(format)
{
case GL_R16UI:
case GL_RED_INTEGER:
return sw::FORMAT_R16UI;
case GL_RG16UI:
case GL_RG_INTEGER:
return sw::FORMAT_G16R16UI;
case GL_RGB16UI:
case GL_RGB_INTEGER:
return sw::FORMAT_X16B16G16R16UI;
case GL_RGBA16UI:
case GL_RGBA_INTEGER:
return sw::FORMAT_A16B16G16R16UI;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
return sw::FORMAT_D32F_LOCKABLE;
default:
UNREACHABLE(format);
}
case GL_INT:
switch(format)
{
case GL_RED_INTEGER:
case GL_R32I:
return sw::FORMAT_R32I;
case GL_RG_INTEGER:
case GL_RG32I:
return sw::FORMAT_G32R32I;
case GL_RGB_INTEGER:
case GL_RGB32I:
return sw::FORMAT_X32B32G32R32I;
case GL_RGBA_INTEGER:
case GL_RGBA32I:
return sw::FORMAT_A32B32G32R32I;
default:
UNREACHABLE(format);
}
case GL_UNSIGNED_INT:
switch(format)
{
case GL_RED_INTEGER:
case GL_R32UI:
return sw::FORMAT_R32UI;
case GL_RG_INTEGER:
case GL_RG32UI:
return sw::FORMAT_G32R32UI;
case GL_RGB_INTEGER:
case GL_RGB32UI:
return sw::FORMAT_X32B32G32R32UI;
case GL_RGBA_INTEGER:
case GL_RGBA32UI:
return sw::FORMAT_A32B32G32R32UI;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32_OES:
return sw::FORMAT_D32F_LOCKABLE;
default:
UNREACHABLE(format);
}
case GL_UNSIGNED_INT_24_8_OES:
if(format == GL_DEPTH_STENCIL || format == GL_DEPTH24_STENCIL8)
{
return sw::FORMAT_D32FS8_TEXTURE;
}
else UNREACHABLE(format);
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
if(format == GL_DEPTH_STENCIL || format == GL_DEPTH32F_STENCIL8)
{
return sw::FORMAT_D32FS8_TEXTURE;
}
else UNREACHABLE(format);
case GL_UNSIGNED_SHORT_4_4_4_4:
return sw::FORMAT_A8R8G8B8;
case GL_UNSIGNED_SHORT_5_5_5_1:
return sw::FORMAT_A8R8G8B8;
case GL_UNSIGNED_SHORT_5_6_5:
return sw::FORMAT_R5G6B5;
case GL_UNSIGNED_INT_2_10_10_10_REV:
if(format == GL_RGB10_A2UI)
{
return sw::FORMAT_A2B10G10R10UI;
}
else
{
return sw::FORMAT_A2B10G10R10;
}
case GL_UNSIGNED_INT_10F_11F_11F_REV:
case GL_UNSIGNED_INT_5_9_9_9_REV: // 5 is the exponent field, not alpha.
return sw::FORMAT_X16B16G16R16F_UNSIGNED;
default:
UNREACHABLE(type);
}
return sw::FORMAT_NULL;
}
// Returns the size, in bytes, of a single client-side pixel.
// OpenGL ES 3.0.5 table 3.2.
static int ComputePixelSize(GLenum format, GLenum type)
{
switch(format)
{
case GL_RED:
case GL_RED_INTEGER:
case GL_ALPHA:
case GL_LUMINANCE:
switch(type)
{
case GL_BYTE: return 1;
case GL_UNSIGNED_BYTE: return 1;
case GL_FLOAT: return 4;
case GL_HALF_FLOAT: return 2;
case GL_HALF_FLOAT_OES: return 2;
case GL_SHORT: return 2;
case GL_UNSIGNED_SHORT: return 2;
case GL_INT: return 4;
case GL_UNSIGNED_INT: return 4;
default: UNREACHABLE(type);
}
break;
case GL_RG:
case GL_RG_INTEGER:
case GL_LUMINANCE_ALPHA:
switch(type)
{
case GL_BYTE: return 2;
case GL_UNSIGNED_BYTE: return 2;
case GL_FLOAT: return 8;
case GL_HALF_FLOAT: return 4;
case GL_HALF_FLOAT_OES: return 4;
case GL_SHORT: return 4;
case GL_UNSIGNED_SHORT: return 4;
case GL_INT: return 8;
case GL_UNSIGNED_INT: return 8;
default: UNREACHABLE(type);
}
break;
case GL_RGB:
case GL_RGB_INTEGER:
switch(type)
{
case GL_BYTE: return 3;
case GL_UNSIGNED_BYTE: return 3;
case GL_UNSIGNED_SHORT_5_6_5: return 2;
case GL_UNSIGNED_INT_10F_11F_11F_REV: return 4;
case GL_UNSIGNED_INT_5_9_9_9_REV: return 4;
case GL_FLOAT: return 12;
case GL_HALF_FLOAT: return 6;
case GL_HALF_FLOAT_OES: return 6;
case GL_SHORT: return 6;
case GL_UNSIGNED_SHORT: return 6;
case GL_INT: return 12;
case GL_UNSIGNED_INT: return 12;
default: UNREACHABLE(type);
}
break;
case GL_RGBA:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
switch(type)
{
case GL_BYTE: return 4;
case GL_UNSIGNED_BYTE: return 4;
case GL_UNSIGNED_SHORT_4_4_4_4: return 2;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return 2;
case GL_UNSIGNED_SHORT_5_5_5_1: return 2;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return 2;
case GL_UNSIGNED_INT_2_10_10_10_REV: return 4;
case GL_FLOAT: return 16;
case GL_HALF_FLOAT: return 8;
case GL_HALF_FLOAT_OES: return 8;
case GL_SHORT: return 8;
case GL_UNSIGNED_SHORT: return 8;
case GL_INT: return 16;
case GL_UNSIGNED_INT: return 16;
default: UNREACHABLE(type);
}
break;
case GL_DEPTH_COMPONENT:
switch(type)
{
case GL_FLOAT: return 4;
case GL_UNSIGNED_SHORT: return 2;
case GL_UNSIGNED_INT: return 4;
default: UNREACHABLE(type);
}
break;
case GL_DEPTH_STENCIL:
switch(type)
{
case GL_UNSIGNED_INT_24_8: return 4;
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: return 8;
default: UNREACHABLE(type);
}
break;
default:
UNREACHABLE(format);
}
return 0;
}
GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
{
ASSERT(alignment > 0 && sw::isPow2(alignment));
GLsizei rawPitch = ComputePixelSize(format, type) * width;
return (rawPitch + alignment - 1) & ~(alignment - 1);
}
size_t ComputePackingOffset(GLenum format, GLenum type, GLsizei width, GLsizei height, const PixelStorageModes &storageModes)
{
GLsizei pitchB = ComputePitch(width, format, type, storageModes.alignment);
return (storageModes.skipImages * height + storageModes.skipRows) * pitchB + storageModes.skipPixels * ComputePixelSize(format, type);
}
inline GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
{
return ComputeCompressedSize(width, 1, format);
}
GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
{
switch(format)
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_ETC1_RGB8_OES:
case GL_COMPRESSED_R11_EAC:
case GL_COMPRESSED_SIGNED_R11_EAC:
case GL_COMPRESSED_RGB8_ETC2:
case GL_COMPRESSED_SRGB8_ETC2:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
return 8 * getNumBlocks(width, height, 4, 4);
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
case GL_COMPRESSED_RG11_EAC:
case GL_COMPRESSED_SIGNED_RG11_EAC:
case GL_COMPRESSED_RGBA8_ETC2_EAC:
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
return 16 * getNumBlocks(width, height, 4, 4);
case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
return 16 * getNumBlocks(width, height, 5, 4);
case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
return 16 * getNumBlocks(width, height, 5, 5);
case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
return 16 * getNumBlocks(width, height, 6, 5);
case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
return 16 * getNumBlocks(width, height, 6, 6);
case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
return 16 * getNumBlocks(width, height, 8, 5);
case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
return 16 * getNumBlocks(width, height, 8, 6);
case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
return 16 * getNumBlocks(width, height, 8, 8);
case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
return 16 * getNumBlocks(width, height, 10, 5);
case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
return 16 * getNumBlocks(width, height, 10, 6);
case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
return 16 * getNumBlocks(width, height, 10, 8);
case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
return 16 * getNumBlocks(width, height, 10, 10);
case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
return 16 * getNumBlocks(width, height, 12, 10);
case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
return 16 * getNumBlocks(width, height, 12, 12);
default:
return 0;
}
}
class ImageImplementation : public Image
{
public:
ImageImplementation(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
: Image(parentTexture, width, height, format, type) {}
ImageImplementation(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLenum format, GLenum type)
: Image(parentTexture, width, height, depth, border, format, type) {}
ImageImplementation(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
: Image(width, height, format, type, pitchP) {}
ImageImplementation(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable)
: Image(width, height, internalFormat, multiSampleDepth, lockable) {}
~ImageImplementation() override
{
sync(); // Wait for any threads that use this image to finish.
}
void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client) override
{
return Image::lockInternal(x, y, z, lock, client);
}
void unlockInternal() override
{
return Image::unlockInternal();
}
void release() override
{
return Image::release();
}
};
Image *Image::create(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
{
return new ImageImplementation(parentTexture, width, height, format, type);
}
Image *Image::create(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLenum format, GLenum type)
{
return new ImageImplementation(parentTexture, width, height, depth, border, format, type);
}
Image *Image::create(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
{
return new ImageImplementation(width, height, format, type, pitchP);
}
Image *Image::create(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable)
{
return new ImageImplementation(width, height, internalFormat, multiSampleDepth, lockable);
}
Image::~Image()
{
// sync() must be called in the destructor of the most derived class to ensure their vtable isn't destroyed
// before all threads are done using this image. Image itself is abstract so it can't be the most derived.
ASSERT(isUnlocked());
if(parentTexture)
{
parentTexture->release();
}
ASSERT(!shared);
}
void *Image::lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client)
{
return Surface::lockInternal(x, y, z, lock, client);
}
void Image::unlockInternal()
{
Surface::unlockInternal();
}
void Image::release()
{
int refs = dereference();
if(refs > 0)
{
if(parentTexture)
{
parentTexture->sweep();
}
}
else
{
delete this;
}
}
void Image::unbind(const egl::Texture *parent)
{
if(parentTexture == parent)
{
parentTexture = nullptr;
}
release();
}
bool Image::isChildOf(const egl::Texture *parent) const
{
return parentTexture == parent;
}
void Image::loadImageData(Context *context, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelStorageModes &unpackParameters, const void *pixels)
{
sw::Format uploadFormat = SelectInternalFormat(format, type);
if(uploadFormat == sw::FORMAT_NULL)
{
return;
}
GLsizei inputWidth = (unpackParameters.rowLength == 0) ? width : unpackParameters.rowLength;
GLsizei inputPitch = ComputePitch(inputWidth, format, type, unpackParameters.alignment);
GLsizei inputHeight = (unpackParameters.imageHeight == 0) ? height : unpackParameters.imageHeight;
char *input = ((char*)pixels) + ComputePackingOffset(format, type, inputWidth, inputHeight, unpackParameters);
if(uploadFormat == internalFormat ||
(uploadFormat == sw::FORMAT_A8B8G8R8 && internalFormat == sw::FORMAT_SRGB8_A8) ||
(uploadFormat == sw::FORMAT_X8B8G8R8 && internalFormat == sw::FORMAT_SRGB8_X8) ||
(uploadFormat == sw::FORMAT_A2B10G10R10 && internalFormat == sw::FORMAT_A2B10G10R10UI))
{
void *buffer = lock(xoffset, yoffset, zoffset, sw::LOCK_WRITEONLY);
if(buffer)
{
// OpenGL ES 3.0.5 table 3.2.
switch(format)
{
case GL_RED:
case GL_RED_INTEGER:
case GL_ALPHA:
case GL_LUMINANCE:
switch(type)
{
case GL_BYTE:
case GL_UNSIGNED_BYTE:
LoadImageData<Bytes_1>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_FLOAT:
ASSERT(format != GL_RED_INTEGER);
LoadImageData<Bytes_4>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
ASSERT(format != GL_RED_INTEGER);
LoadImageData<Bytes_2>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
LoadImageData<Bytes_2>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_INT:
case GL_UNSIGNED_INT:
LoadImageData<Bytes_4>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
default:
UNREACHABLE(type);
}
break;
case GL_RG:
case GL_RG_INTEGER:
case GL_LUMINANCE_ALPHA:
switch(type)
{
case GL_BYTE:
case GL_UNSIGNED_BYTE:
LoadImageData<Bytes_2>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_FLOAT:
ASSERT(format != GL_RG_INTEGER);
LoadImageData<Bytes_8>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
ASSERT(format != GL_RG_INTEGER);
LoadImageData<Bytes_4>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
LoadImageData<Bytes_4>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_INT:
case GL_UNSIGNED_INT:
LoadImageData<Bytes_8>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
default:
UNREACHABLE(type);
}
break;
case GL_RGB:
case GL_RGB_INTEGER:
switch(type)
{
case GL_BYTE:
LoadImageData<ByteRGB>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_BYTE:
LoadImageData<UByteRGB>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_SHORT_5_6_5:
ASSERT(format == GL_RGB);
LoadImageData<Bytes_2>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_INT_10F_11F_11F_REV:
ASSERT(format == GL_RGB);
LoadImageData<R11G11B10F>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_INT_5_9_9_9_REV:
ASSERT(format == GL_RGB);
LoadImageData<RGB9E5>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_FLOAT:
ASSERT(format == GL_RGB);
LoadImageData<FloatRGB>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
ASSERT(format == GL_RGB);
LoadImageData<HalfFloatRGB>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_SHORT:
LoadImageData<ShortRGB>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_SHORT:
LoadImageData<UShortRGB>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_INT:
LoadImageData<IntRGB>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_INT:
LoadImageData<UIntRGB>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
default:
UNREACHABLE(type);
}
break;
case GL_RGBA:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
switch(type)
{
case GL_BYTE:
case GL_UNSIGNED_BYTE:
LoadImageData<Bytes_4>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
ASSERT(format == GL_RGBA);
LoadImageData<RGBA4444>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
// case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
// ASSERT(format == GL_BGRA_EXT);
// LoadImageData<ABGR4444>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
// break;
case GL_UNSIGNED_SHORT_5_5_5_1:
ASSERT(format == GL_RGBA);
LoadImageData<RGBA5551>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
// case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
// ASSERT(format == GL_BGRA_EXT);
// LoadImageData<ABGR5551>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
// break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
ASSERT(format != GL_BGRA_EXT);
LoadImageData<Bytes_4>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_FLOAT:
ASSERT(format == GL_RGBA);
LoadImageData<Bytes_16>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
ASSERT(format == GL_RGBA);
LoadImageData<Bytes_8>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
ASSERT(format != GL_BGRA_EXT);
LoadImageData<Bytes_8>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_INT:
case GL_UNSIGNED_INT:
ASSERT(format != GL_BGRA_EXT);
LoadImageData<Bytes_16>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
default:
UNREACHABLE(type);
}
break;
case GL_DEPTH_COMPONENT:
switch(type)
{
case GL_FLOAT:
LoadImageData<D32F>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_SHORT:
LoadImageData<D16>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
case GL_UNSIGNED_INT:
LoadImageData<D32>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
break;
default:
UNREACHABLE(type);
}
break;
case GL_DEPTH_STENCIL:
switch(type)
{
case GL_UNSIGNED_INT_24_8:
loadD24S8ImageData(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, input, buffer);
break;
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
loadD32FS8ImageData(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, input, buffer);
break;
default:
UNREACHABLE(type);
}
break;
default:
UNREACHABLE(format);
}
}
unlock();
}
else
{
sw::Surface *source = sw::Surface::create(width, height, depth, ConvertFormatType(format, type), input, inputPitch, inputPitch * inputHeight);
sw::Rect sourceRect(0, 0, width, height);
sw::Rect destRect(xoffset, yoffset, xoffset + width, yoffset + height);
context->blit(source, sourceRect, this, destRect);
delete source;
}
}
void Image::loadD24S8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer)
{
LoadImageData<D24>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, 0, 0, sw::PUBLIC));
if(stencil)
{
LoadImageData<S8>(width, height, depth, inputPitch, inputHeight, getStencilPitchB(), getHeight(), input, stencil);
unlockStencil();
}
}
void Image::loadD32FS8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer)
{
LoadImageData<D32FS8>(width, height, depth, inputPitch, inputHeight, getPitch(), getSlice(), input, buffer);
unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, 0, 0, sw::PUBLIC));
if(stencil)
{
LoadImageData<S24_8>(width, height, depth, inputPitch, inputHeight, getStencilPitchB(), getHeight(), input, stencil);
unlockStencil();
}
}
void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
{
int inputPitch = ComputeCompressedPitch(width, format);
int inputSlice = imageSize / depth;
int rows = inputSlice / inputPitch;
void *buffer = lock(xoffset, yoffset, zoffset, sw::LOCK_WRITEONLY);
if(buffer)
{
for(int z = 0; z < depth; z++)
{
for(int y = 0; y < rows; y++)
{
GLbyte *dest = (GLbyte*)buffer + y * getPitch() + z * getSlice();
GLbyte *source = (GLbyte*)pixels + y * inputPitch + z * inputSlice;
memcpy(dest, source, inputPitch);
}
}
}
unlock();
}
}