|  | // 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 "Texture.h" | 
|  | #include "utilities.h" | 
|  | #include "../common/debug.h" | 
|  | #include "Common/Thread.hpp" | 
|  |  | 
|  | #define _GDI32_ | 
|  | #include <windows.h> | 
|  | #include <GL/GL.h> | 
|  | #include <GL/glext.h> | 
|  |  | 
|  | namespace gl | 
|  | { | 
|  | static sw::Resource *getParentResource(Texture *texture) | 
|  | { | 
|  | if(texture) | 
|  | { | 
|  | return texture->getResource(); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | Image::Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type) | 
|  | : parentTexture(parentTexture), width(width), height(height), format(format), type(type) | 
|  | , internalFormat(selectInternalFormat(format, type)), multiSampleDepth(1) | 
|  | , sw::Surface(getParentResource(parentTexture), width, height, 1, selectInternalFormat(format, type), true, true) | 
|  | { | 
|  | referenceCount = 1; | 
|  | } | 
|  |  | 
|  | Image::Image(Texture *parentTexture, GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable, bool renderTarget) | 
|  | : parentTexture(parentTexture), width(width), height(height), internalFormat(internalFormat), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), multiSampleDepth(multiSampleDepth) | 
|  | , sw::Surface(getParentResource(parentTexture), width, height, multiSampleDepth, internalFormat, lockable, renderTarget) | 
|  | { | 
|  | referenceCount = 1; | 
|  | } | 
|  |  | 
|  | Image::~Image() | 
|  | { | 
|  | ASSERT(referenceCount == 0); | 
|  | } | 
|  |  | 
|  | void *Image::lock(unsigned int left, unsigned int top, sw::Lock lock) | 
|  | { | 
|  | return lockExternal(left, top, 0, lock, sw::PUBLIC); | 
|  | } | 
|  |  | 
|  | unsigned int Image::getPitch() const | 
|  | { | 
|  | return getExternalPitchB(); | 
|  | } | 
|  |  | 
|  | void Image::unlock() | 
|  | { | 
|  | unlockExternal(); | 
|  | } | 
|  |  | 
|  | 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(); | 
|  | } | 
|  |  | 
|  | int Image::getWidth() | 
|  | { | 
|  | return width; | 
|  | } | 
|  |  | 
|  | int Image::getHeight() | 
|  | { | 
|  | return height; | 
|  | } | 
|  |  | 
|  | GLenum Image::getFormat() | 
|  | { | 
|  | return format; | 
|  | } | 
|  |  | 
|  | GLenum Image::getType() | 
|  | { | 
|  | return type; | 
|  | } | 
|  |  | 
|  | sw::Format Image::getInternalFormat() | 
|  | { | 
|  | return internalFormat; | 
|  | } | 
|  |  | 
|  | int Image::getMultiSampleDepth() | 
|  | { | 
|  | return multiSampleDepth; | 
|  | } | 
|  |  | 
|  | void Image::addRef() | 
|  | { | 
|  | if(parentTexture) | 
|  | { | 
|  | return parentTexture->addRef(); | 
|  | } | 
|  |  | 
|  | sw::atomicIncrement(&referenceCount); | 
|  | } | 
|  |  | 
|  | void Image::release() | 
|  | { | 
|  | if(parentTexture) | 
|  | { | 
|  | return parentTexture->release(); | 
|  | } | 
|  |  | 
|  | if(referenceCount > 0) | 
|  | { | 
|  | sw::atomicDecrement(&referenceCount); | 
|  | } | 
|  |  | 
|  | if(referenceCount == 0) | 
|  | { | 
|  | delete this; | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::unbind() | 
|  | { | 
|  | parentTexture = 0; | 
|  |  | 
|  | release(); | 
|  | } | 
|  |  | 
|  | sw::Format Image::selectInternalFormat(GLenum format, GLenum type) | 
|  | { | 
|  | if(type == GL_NONE && format == GL_NONE) | 
|  | { | 
|  | return sw::FORMAT_NULL; | 
|  | } | 
|  | else | 
|  | #if S3TC_SUPPORT | 
|  | if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || | 
|  | format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) | 
|  | { | 
|  | return sw::FORMAT_DXT1; | 
|  | } | 
|  | else if(format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) | 
|  | { | 
|  | return sw::FORMAT_DXT3; | 
|  | } | 
|  | else if(format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) | 
|  | { | 
|  | return sw::FORMAT_DXT5; | 
|  | } | 
|  | else | 
|  | #endif | 
|  | if(type == GL_FLOAT) | 
|  | { | 
|  | return sw::FORMAT_A32B32G32R32F; | 
|  | } | 
|  | else if(type == GL_HALF_FLOAT) | 
|  | { | 
|  | return sw::FORMAT_A16B16G16R16F; | 
|  | } | 
|  | else if(type == GL_UNSIGNED_BYTE) | 
|  | { | 
|  | if(format == GL_LUMINANCE) | 
|  | { | 
|  | return sw::FORMAT_L8; | 
|  | } | 
|  | else if(format == GL_LUMINANCE_ALPHA) | 
|  | { | 
|  | return sw::FORMAT_A8L8; | 
|  | } | 
|  | else if(format == GL_RGBA || format == GL_BGRA_EXT) | 
|  | { | 
|  | return sw::FORMAT_A8R8G8B8; | 
|  | } | 
|  | else if(format == GL_RGB) | 
|  | { | 
|  | return sw::FORMAT_X8R8G8B8; | 
|  | } | 
|  | else if(format == GL_ALPHA) | 
|  | { | 
|  | return sw::FORMAT_A8; | 
|  | } | 
|  | else UNREACHABLE(format); | 
|  | } | 
|  | else if(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT) | 
|  | { | 
|  | if(format == GL_DEPTH_COMPONENT) | 
|  | { | 
|  | return sw::FORMAT_D32FS8_TEXTURE; | 
|  | } | 
|  | else UNREACHABLE(format); | 
|  | } | 
|  | else if(type == GL_UNSIGNED_INT_24_8_EXT) | 
|  | { | 
|  | if(format == GL_DEPTH_STENCIL_EXT) | 
|  | { | 
|  | return sw::FORMAT_D32FS8_TEXTURE; | 
|  | } | 
|  | else UNREACHABLE(format); | 
|  | } | 
|  | else if(type == GL_UNSIGNED_SHORT_4_4_4_4) | 
|  | { | 
|  | return sw::FORMAT_A8R8G8B8; | 
|  | } | 
|  | else if(type == GL_UNSIGNED_SHORT_5_5_5_1) | 
|  | { | 
|  | return sw::FORMAT_A8R8G8B8; | 
|  | } | 
|  | else if(type == GL_UNSIGNED_SHORT_5_6_5) | 
|  | { | 
|  | return sw::FORMAT_R5G6B5; | 
|  | } | 
|  | else if(type == GL_UNSIGNED_INT_8_8_8_8_REV) | 
|  | { | 
|  | return sw::FORMAT_A8R8G8B8; | 
|  | } | 
|  |  | 
|  | else UNREACHABLE(type); | 
|  |  | 
|  | return sw::FORMAT_A8R8G8B8; | 
|  | } | 
|  |  | 
|  | void Image::loadImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLint unpackAlignment, const void *input) | 
|  | { | 
|  | GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment); | 
|  | void *buffer = lock(0, 0, sw::LOCK_WRITEONLY); | 
|  |  | 
|  | if(buffer) | 
|  | { | 
|  | switch(type) | 
|  | { | 
|  | case GL_UNSIGNED_BYTE: | 
|  | case GL_UNSIGNED_INT_8_8_8_8_REV: | 
|  | switch(format) | 
|  | { | 
|  | case GL_ALPHA: | 
|  | loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_LUMINANCE: | 
|  | loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_LUMINANCE_ALPHA: | 
|  | loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_RGB: | 
|  | loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_RGBA: | 
|  | loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_BGRA_EXT: | 
|  | loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | default: UNREACHABLE(format); | 
|  | } | 
|  | break; | 
|  | case GL_UNSIGNED_SHORT_5_6_5: | 
|  | switch(format) | 
|  | { | 
|  | case GL_RGB: | 
|  | loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | default: UNREACHABLE(format); | 
|  | } | 
|  | break; | 
|  | case GL_UNSIGNED_SHORT_4_4_4_4: | 
|  | switch(format) | 
|  | { | 
|  | case GL_RGBA: | 
|  | loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | default: UNREACHABLE(format); | 
|  | } | 
|  | break; | 
|  | case GL_UNSIGNED_SHORT_5_5_5_1: | 
|  | switch(format) | 
|  | { | 
|  | case GL_RGBA: | 
|  | loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | default: UNREACHABLE(format); | 
|  | } | 
|  | break; | 
|  | case GL_FLOAT: | 
|  | switch(format) | 
|  | { | 
|  | // float textures are converted to RGBA, not BGRA | 
|  | case GL_ALPHA: | 
|  | loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_LUMINANCE: | 
|  | loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_LUMINANCE_ALPHA: | 
|  | loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_RGB: | 
|  | loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_RGBA: | 
|  | loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | default: UNREACHABLE(format); | 
|  | } | 
|  | break; | 
|  | case GL_HALF_FLOAT: | 
|  | switch(format) | 
|  | { | 
|  | // float textures are converted to RGBA, not BGRA | 
|  | case GL_ALPHA: | 
|  | loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_LUMINANCE: | 
|  | loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_LUMINANCE_ALPHA: | 
|  | loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_RGB: | 
|  | loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_RGBA: | 
|  | loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | default: UNREACHABLE(format); | 
|  | } | 
|  | break; | 
|  | case GL_UNSIGNED_SHORT: | 
|  | loadD16ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_UNSIGNED_INT: | 
|  | loadD32ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | case GL_UNSIGNED_INT_24_8_EXT: | 
|  | loadD24S8ImageData(xoffset, yoffset, width, height, inputPitch, input, buffer); | 
|  | break; | 
|  | default: UNREACHABLE(type); | 
|  | } | 
|  | } | 
|  |  | 
|  | unlock(); | 
|  | } | 
|  |  | 
|  | void Image::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch; | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset; | 
|  |  | 
|  | memcpy(dest, source, width); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = 0; | 
|  | dest[4 * x + 1] = 0; | 
|  | dest[4 * x + 2] = 0; | 
|  | dest[4 * x + 3] = source[x]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = 0; | 
|  | dest[4 * x + 1] = 0; | 
|  | dest[4 * x + 2] = 0; | 
|  | dest[4 * x + 3] = source[x]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch; | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset; | 
|  |  | 
|  | memcpy(dest, source, width); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = source[x]; | 
|  | dest[4 * x + 1] = source[x]; | 
|  | dest[4 * x + 2] = source[x]; | 
|  | dest[4 * x + 3] = 1.0f; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = source[x]; | 
|  | dest[4 * x + 1] = source[x]; | 
|  | dest[4 * x + 2] = source[x]; | 
|  | dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch; | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 2; | 
|  |  | 
|  | memcpy(dest, source, width * 2); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = source[2*x+0]; | 
|  | dest[4 * x + 1] = source[2*x+0]; | 
|  | dest[4 * x + 2] = source[2*x+0]; | 
|  | dest[4 * x + 3] = source[2*x+1]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = source[2*x+0]; | 
|  | dest[4 * x + 1] = source[2*x+0]; | 
|  | dest[4 * x + 2] = source[2*x+0]; | 
|  | dest[4 * x + 3] = source[2*x+1]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch; | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4; | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = source[x * 3 + 2]; | 
|  | dest[4 * x + 1] = source[x * 3 + 1]; | 
|  | dest[4 * x + 2] = source[x * 3 + 0]; | 
|  | dest[4 * x + 3] = 0xFF; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 2; | 
|  |  | 
|  | memcpy(dest, source, width * 2); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = source[x * 3 + 0]; | 
|  | dest[4 * x + 1] = source[x * 3 + 1]; | 
|  | dest[4 * x + 2] = source[x * 3 + 2]; | 
|  | dest[4 * x + 3] = 1.0f; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned short *dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[4 * x + 0] = source[x * 3 + 0]; | 
|  | dest[4 * x + 1] = source[x * 3 + 1]; | 
|  | dest[4 * x + 2] = source[x * 3 + 2]; | 
|  | dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | unsigned int rgba = source[x]; | 
|  | dest[x] = (rgba & 0xFF00FF00) | ((rgba << 16) & 0x00FF0000) | ((rgba >> 16) & 0x000000FF); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4; | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | unsigned short rgba = source[x]; | 
|  | dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); | 
|  | dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); | 
|  | dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); | 
|  | dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4; | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | unsigned short rgba = source[x]; | 
|  | dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); | 
|  | dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); | 
|  | dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); | 
|  | dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const float *source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 16); | 
|  |  | 
|  | memcpy(dest, source, width * 16); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch; | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 8; | 
|  |  | 
|  | memcpy(dest, source, width * 8); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned char *source = static_cast<const unsigned char*>(input) + y * inputPitch; | 
|  | unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4; | 
|  |  | 
|  | memcpy(dest, source, width*4); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadD16ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[x] = (float)source[x] / 0xFFFF; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadD32ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) const | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[x] = (float)source[x] / 0xFFFFFFFF; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void Image::loadD24S8ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, int inputPitch, const void *input, void *buffer) | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | float *dest = reinterpret_cast<float*>(static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4); | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[x] = (float)(source[x] & 0xFFFFFF00) / 0xFFFFFF00; | 
|  | } | 
|  | } | 
|  |  | 
|  | unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, 0, 0, sw::PUBLIC)); | 
|  |  | 
|  | if(stencil) | 
|  | { | 
|  | for(int y = 0; y < height; y++) | 
|  | { | 
|  | const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch); | 
|  | unsigned char *dest = static_cast<unsigned char*>(stencil) + (y + yoffset) * getStencilPitchB() + xoffset; | 
|  |  | 
|  | for(int x = 0; x < width; x++) | 
|  | { | 
|  | dest[x] = static_cast<unsigned char>(source[x] & 0x000000FF);   // FIXME: Quad layout | 
|  | } | 
|  | } | 
|  |  | 
|  | 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 rows = imageSize / inputPitch; | 
|  | void *buffer = lock(xoffset, yoffset, sw::LOCK_WRITEONLY); | 
|  |  | 
|  | if(buffer) | 
|  | { | 
|  | for(int i = 0; i < rows; i++) | 
|  | { | 
|  | memcpy((void*)((GLbyte*)buffer + i * getPitch()), (void*)((GLbyte*)pixels + i * inputPitch), inputPitch); | 
|  | } | 
|  | } | 
|  |  | 
|  | unlock(); | 
|  | } | 
|  | } |