OSDN Git Service

Make Blitter part of Renderer.
[android-x86/external-swiftshader.git] / src / OpenGL / common / Image.cpp
index 73a8656..d3fe20e 100644 (file)
@@ -1,17 +1,20 @@
-// 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"
@@ -469,7 +472,9 @@ namespace egl
                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;
@@ -500,6 +505,40 @@ namespace egl
                        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);
                }
@@ -624,6 +663,7 @@ namespace egl
                                return sw::FORMAT_G32R32F;
                        case GL_RGB:
                        case GL_RGB32F:
+                               return sw::FORMAT_X32B32G32R32F;
                        case GL_RGBA:
                        case GL_RGBA32F:
                                return sw::FORMAT_A32B32G32R32F;
@@ -993,6 +1033,8 @@ namespace egl
                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:
@@ -1058,6 +1100,12 @@ namespace egl
                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);
+       }
+
        inline GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
        {
                return ComputeCompressedSize(width, 1, format);
@@ -1069,7 +1117,7 @@ namespace egl
                {
                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:
@@ -1130,29 +1178,98 @@ namespace egl
                }
        }
 
-       Image::~Image()
+       class ImageImplementation : public Image
        {
-               ASSERT(!shared);
+       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);
        }
 
-       void Image::addRef()
+       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)
                {
-                       return parentTexture->addRef();
+                       parentTexture->release();
                }
 
-               Object::addRef();
+               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();
+                       }
+               }
+               else
+               {
+                       delete this;
                }
-
-               Object::release();
        }
 
        void Image::unbind(const egl::Texture *parent)
@@ -1170,17 +1287,19 @@ namespace egl
                return parentTexture == parent;
        }
 
-       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)
+       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);
@@ -1522,13 +1641,13 @@ namespace egl
                                        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:
@@ -1540,7 +1659,7 @@ namespace egl
                                        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:
@@ -1565,10 +1684,11 @@ namespace egl
                }
                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;
                }
        }
 
@@ -1576,7 +1696,7 @@ namespace egl
        {
                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)
                {
@@ -1590,7 +1710,7 @@ namespace egl
        {
                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)
                {