-// SwiftShader Software Renderer
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
-// Copyright(c) 2005-2013 TransGaming Inc.
+// 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
//
-// All rights reserved. No part of this software may be copied, distributed, transmitted,
-// transcribed, stored in a retrieval system, translated into any human or computer
-// language by any means, or disclosed to third parties without the explicit written
-// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
-// or implied, including but not limited to any patent rights, are granted to you.
+// 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 "Renderer/Blitter.hpp"
+#include "../libEGL/Context.hpp"
#include "../libEGL/Texture.hpp"
#include "../common/debug.h"
#include "Common/Math.hpp"
#include "Common/Thread.hpp"
-#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
#include <string.h>
case GL_BGRA8_EXT:
switch(type)
{
- case GL_UNSIGNED_BYTE: return sw::FORMAT_A8R8G8B8;
+ 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;
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;
+ 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;
+ default: UNREACHABLE(type);
+ }
+ break;
default:
UNREACHABLE(format);
}
return sw::FORMAT_G32R32F;
case GL_RGB:
case GL_RGB32F:
+ return sw::FORMAT_X32B32G32R32F;
case GL_RGBA:
case GL_RGBA32F:
return sw::FORMAT_A32B32G32R32F;
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
return sizeof(unsigned short);
case GL_UNSIGNED_INT_10F_11F_11F_REV:
case GL_UNSIGNED_INT_5_9_9_9_REV:
return (rawPitch + alignment - 1) & ~(alignment - 1);
}
+ size_t ComputePackingOffset(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, GLint skipImages, GLint skipRows, GLint skipPixels)
+ {
+ GLsizei pitchB = ComputePitch(width, format, type, alignment);
+ return (skipImages * height + skipRows) * pitchB + skipPixels * ComputePixelSize(format, type);
+ }
- GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
+ inline GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
{
return ComputeCompressedSize(width, 1, format);
}
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_ETC1_RGB8_OES:
+ case GL_ETC1_RGB8_OES:
case GL_COMPRESSED_R11_EAC:
case GL_COMPRESSED_SIGNED_R11_EAC:
case GL_COMPRESSED_RGB8_ETC2:
}
}
- Image::~Image()
+ 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, GLenum format, GLenum type)
+ : Image(parentTexture, width, height, depth, 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, GLenum format, GLenum type)
+ {
+ return new ImageImplementation(parentTexture, width, height, depth, format, type);
+ }
+
+ Image *Image::create(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
{
- ASSERT(referenceCount == 0);
+ return new ImageImplementation(width, height, format, type, pitchP);
}
- void Image::addRef()
+ 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)
{
- return parentTexture->addRef();
+ parentTexture->release();
}
- int newCount = sw::atomicIncrement(&referenceCount);
- LOGLOCK("%s image=%p referenceCount=%d", __FUNCTION__, this, newCount);
+
+ 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()
{
- if(parentTexture)
+ int refs = dereference();
+
+ if(refs > 0)
{
- return parentTexture->release();
+ if(parentTexture)
+ {
+ parentTexture->sweep();
+ }
}
-
- int newCount = sw::atomicDecrement(&referenceCount);
- LOGLOCK("%s image=%p referenceCount=%d", __FUNCTION__, this, newCount);
- if (newCount == 0)
+ else
{
- ASSERT(!shared); // Should still hold a reference if eglDestroyImage hasn't been called
delete this;
}
}
{
if(parentTexture == parent)
{
- parentTexture = 0;
+ parentTexture = nullptr;
}
release();
}
- void Image::loadImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const UnpackInfo& unpackInfo, const void *input)
+ 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 UnpackInfo& unpackInfo, const void *input)
{
- GLsizei inputPitch = ComputePitch((unpackInfo.rowLength == 0) ? width : unpackInfo.rowLength, format, type, unpackInfo.alignment);
- GLsizei inputHeight = (unpackInfo.imageHeight == 0) ? height : unpackInfo.imageHeight;
- input = ((char*)input) + (unpackInfo.skipImages * inputHeight + unpackInfo.skipRows) * inputPitch + unpackInfo.skipPixels;
sw::Format selectedInternalFormat = SelectInternalFormat(format, type);
if(selectedInternalFormat == sw::FORMAT_NULL)
{
return;
}
+ GLsizei inputWidth = (unpackInfo.rowLength == 0) ? width : unpackInfo.rowLength;
+ GLsizei inputPitch = ComputePitch(inputWidth, format, type, unpackInfo.alignment);
+ GLsizei inputHeight = (unpackInfo.imageHeight == 0) ? height : unpackInfo.imageHeight;
+ input = ((char*)input) + ComputePackingOffset(format, type, inputWidth, inputHeight, unpackInfo.alignment, unpackInfo.skipImages, unpackInfo.skipRows, unpackInfo.skipPixels);
+
if(selectedInternalFormat == internalFormat)
{
void *buffer = lock(0, 0, sw::LOCK_WRITEONLY);
case GL_RED_INTEGER:
case GL_ALPHA:
case GL_LUMINANCE:
- LoadImageData<Bytes_2>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+ LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
case GL_RG32UI:
case GL_RG:
case GL_RG_INTEGER:
case GL_LUMINANCE_ALPHA:
- LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+ LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
case GL_RGB32UI:
case GL_RGB:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
- LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+ LoadImageData<Bytes_16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
}
else
{
- sw::Surface source(width, height, depth, ConvertFormatType(format, type), const_cast<void*>(input), inputPitch, inputPitch * inputHeight);
+ sw::Surface *source = sw::Surface::create(width, height, depth, ConvertFormatType(format, type), const_cast<void*>(input), inputPitch, inputPitch * inputHeight);
sw::Rect sourceRect(0, 0, width, height);
sw::Rect destRect(xoffset, yoffset, xoffset + width, yoffset + height);
- sw::blitter.blit(&source, sourceRect, this, destRect, false);
+ context->blit(source, sourceRect, this, destRect);
+ delete source;
}
}
{
LoadImageData<D24>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
- unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, sw::PUBLIC));
+ unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, 0, 0, sw::PUBLIC));
if(stencil)
{
{
LoadImageData<D32F>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
- unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, sw::PUBLIC));
+ unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, 0, 0, sw::PUBLIC));
if(stencil)
{