OSDN Git Service

First simplest 3D mipmap implementation
authorAlexis Hetu <sugoi@google.com>
Tue, 24 Feb 2015 19:33:49 +0000 (14:33 -0500)
committerAlexis Hétu <sugoi@google.com>
Fri, 17 Apr 2015 14:29:38 +0000 (14:29 +0000)
Bug 19126833

Change-Id: Idd67457542deb1408812bce2c796b275a7b19f0e
Reviewed-on: https://swiftshader-review.googlesource.com/2420
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
src/OpenGL/libGLESv2/Device.cpp
src/OpenGL/libGLESv2/Device.hpp
src/OpenGL/libGLESv2/Texture.cpp
src/Renderer/Blitter.cpp
src/Renderer/Blitter.hpp
src/Renderer/Renderer.cpp
src/Renderer/Renderer.hpp

index 0f5f7b9..499e3e3 100644 (file)
@@ -681,6 +681,70 @@ namespace es2
                return true;\r
        }\r
 \r
+       bool Device::stretchCube(egl::Image *source, egl::Image *dest)\r
+       {\r
+               if(!source || !dest || Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat()))\r
+               {\r
+                       ERR("Invalid parameters");\r
+                       return false;\r
+               }\r
+\r
+               int sWidth  = source->getExternalWidth();\r
+               int sHeight = source->getExternalHeight();\r
+               int sDepth  = source->getExternalDepth();\r
+               int dWidth  = dest->getExternalWidth();\r
+               int dHeight = dest->getExternalHeight();\r
+               int dDepth  = dest->getExternalDepth();\r
+\r
+               bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth);\r
+               bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();\r
+               bool alpha0xFF = false;\r
+\r
+               if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||\r
+                  (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))\r
+               {\r
+                       equalFormats = true;\r
+                       alpha0xFF = true;\r
+               }\r
+\r
+               if(!scaling && equalFormats)\r
+               {\r
+                       unsigned int sourcePitch = source->getInternalPitchB();\r
+                       unsigned int destPitch = dest->getInternalPitchB();\r
+                       unsigned int bytes = dWidth * Image::bytes(source->getInternalFormat());\r
+\r
+                       for(int z = 0; z < dDepth; ++z)\r
+                       {\r
+                               unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC);\r
+                               unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC);\r
+                               for(int y = 0; y < dHeight; ++y)\r
+                               {\r
+                                       memcpy(destBytes, sourceBytes, bytes);\r
+\r
+                                       if(alpha0xFF)\r
+                                       {\r
+                                               for(int x = 0; x < dWidth; ++x)\r
+                                               {\r
+                                                       destBytes[4 * x + 3] = 0xFF;\r
+                                               }\r
+                                       }\r
+\r
+                                       sourceBytes += sourcePitch;\r
+                                       destBytes += destPitch;\r
+                               }\r
+                       }\r
+\r
+                       source->unlockInternal();\r
+                       dest->unlockInternal();\r
+               }\r
+               else\r
+               {\r
+                       blit3D(source, dest);\r
+               }\r
+\r
+               return true;\r
+       }\r
+\r
        bool Device::bindResources()\r
        {\r
                if(!bindViewport())\r
index cc3ea10..04df465 100644 (file)
@@ -70,6 +70,7 @@ namespace es2
                virtual void setViewport(const Viewport &viewport);\r
 \r
                virtual bool stretchRect(egl::Image *sourceSurface, const sw::SliceRect *sourceRect, egl::Image *destSurface, const sw::SliceRect *destRect, bool filter);\r
+               virtual bool stretchCube(egl::Image *sourceSurface, egl::Image *destSurface);\r
                virtual void finish();\r
 \r
        private:\r
index a9002a2..f1b3d46 100644 (file)
@@ -1723,7 +1723,29 @@ bool Texture3D::isDepth(GLenum target, GLint level) const
 \r
 void Texture3D::generateMipmaps()\r
 {\r
-       UNIMPLEMENTED();\r
+       if(!image[0])\r
+       {\r
+               return;   // FIXME: error?\r
+       }\r
+\r
+       unsigned int q = log2(std::max(std::max(image[0]->getWidth(), image[0]->getHeight()), image[0]->getDepth()));\r
+\r
+       for(unsigned int i = 1; i <= q; i++)\r
+       {\r
+               if(image[i])\r
+               {\r
+                       image[i]->unbind(this);\r
+               }\r
+\r
+               image[i] = new Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), std::max(image[0]->getDepth() >> i, 1), image[0]->getFormat(), image[0]->getType());\r
+\r
+               if(!image[i])\r
+               {\r
+                       return error(GL_OUT_OF_MEMORY);\r
+               }\r
+\r
+               getDevice()->stretchCube(image[i - 1], image[i]);\r
+       }\r
 }\r
 \r
 egl::Image *Texture3D::getImage(unsigned int level)\r
index 53bd7cc..99a5664 100644 (file)
@@ -53,8 +53,8 @@ namespace sw
                source->lockInternal(sRect.x0, sRect.y0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
                dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
 
-               float w = 1.0f / (dRect.x1 - dRect.x0) * (sRect.x1 - sRect.x0);
-               float h = 1.0f / (dRect.y1 - dRect.y0) * (sRect.y1 - sRect.y0);
+               float w = static_cast<float>(sRect.x1 - sRect.x0) / static_cast<float>(dRect.x1 - dRect.x0);
+               float h = static_cast<float>(sRect.y1 - sRect.y0) / static_cast<float>(dRect.y1 - dRect.y0);
 
                const float xStart = (float)sRect.x0 + 0.5f * w;
                float y = (float)sRect.y0 + 0.5f * h;
@@ -88,6 +88,36 @@ namespace sw
                dest->unlockInternal();
        }
 
+       void Blitter::blit3D(Surface *source, Surface *dest)
+       {
+               source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
+               dest->lockInternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
+
+               float w = static_cast<float>(source->getExternalWidth())  / static_cast<float>(dest->getExternalWidth());
+               float h = static_cast<float>(source->getExternalHeight()) / static_cast<float>(dest->getExternalHeight());
+               float d = static_cast<float>(source->getExternalDepth())  / static_cast<float>(dest->getExternalDepth());
+
+               float z = 0.5f * d;
+               for(int k = 0; k < dest->getExternalDepth(); ++k)
+               {
+                       float y = 0.5f * h;
+                       for(int j = 0; j < dest->getExternalHeight(); ++j)
+                       {
+                               float x = 0.5f * w;
+                               for(int i = 0; i < dest->getExternalWidth(); ++i)
+                               {
+                                       dest->writeInternal(i, j, k, source->sampleInternal(x, y, z));
+                                       x += w;
+                               }
+                               y += h;
+                       }
+                       z += d;
+               }
+
+               source->unlockInternal();
+               dest->unlockInternal();
+       }
+
        bool Blitter::read(Float4 &c, Pointer<Byte> element, Format format)
        {
                c = Float4(1.0f, 1.0f, 1.0f, 1.0f);
index d676a12..57829fb 100644 (file)
@@ -28,6 +28,7 @@ namespace sw
                virtual ~Blitter();\r
 \r
                void blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter);\r
+               void blit3D(Surface *source, Surface *dest);\r
 \r
        private:\r
                bool read(Float4 &color, Pointer<Byte> element, Format format);\r
index cbc961c..732c959 100644 (file)
@@ -190,6 +190,11 @@ namespace sw
                blitter.blit(source, sRect, dest, dRect, filter);
        }
 
+       void Renderer::blit3D(Surface *source, Surface *dest)
+       {
+               blitter.blit3D(source, dest);
+       }
+
        void Renderer::draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update)
        {
                #ifndef NDEBUG
index 0631acd..e4e8e71 100644 (file)
@@ -271,6 +271,7 @@ namespace sw
                virtual ~Renderer();
 
                virtual void blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter);
+               virtual void blit3D(Surface *source, Surface *dest);
                virtual void draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update = true);
 
                virtual void setIndexBuffer(Resource *indexBuffer);