OSDN Git Service

Functionality to update borders of cube textures.
authorAlexis Hetu <sugoi@google.com>
Tue, 29 Nov 2016 22:17:26 +0000 (17:17 -0500)
committerNicolas Capens <nicolascapens@google.com>
Fri, 1 Dec 2017 15:34:13 +0000 (15:34 +0000)
The cube texture borders will be used for linear interpolation, in
order to produce seamless edges.

Change-Id: Idd17c72c6aaf7dcc65188b065ac8ba179b58cc37
Reviewed-on: https://swiftshader-review.googlesource.com/8209
Tested-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
src/OpenGL/libGLESv2/Texture.cpp
src/OpenGL/libGLESv2/Texture.h
src/Renderer/Surface.cpp
src/Renderer/Surface.hpp

index 784d3fd..273c7ad 100644 (file)
@@ -1246,6 +1246,52 @@ bool TextureCubeMap::isMipmapCubeComplete() const
        return true;
 }
 
+void TextureCubeMap::updateBorders(int level)
+{
+       egl::Image *posX = image[CubeFaceIndex(GL_TEXTURE_CUBE_MAP_POSITIVE_X)][level];
+       egl::Image *negX = image[CubeFaceIndex(GL_TEXTURE_CUBE_MAP_NEGATIVE_X)][level];
+       egl::Image *posY = image[CubeFaceIndex(GL_TEXTURE_CUBE_MAP_POSITIVE_Y)][level];
+       egl::Image *negY = image[CubeFaceIndex(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y)][level];
+       egl::Image *posZ = image[CubeFaceIndex(GL_TEXTURE_CUBE_MAP_POSITIVE_Z)][level];
+       egl::Image *negZ = image[CubeFaceIndex(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)][level];
+
+       if(!posX || !negX || !posY || !negY || !posZ || !negZ)
+       {
+               return;
+       }
+
+       // Copy top / bottom first.
+       posX->copyCubeEdge(sw::Surface::BOTTOM, negY, sw::Surface::RIGHT);
+       posY->copyCubeEdge(sw::Surface::BOTTOM, posZ, sw::Surface::TOP);
+       posZ->copyCubeEdge(sw::Surface::BOTTOM, negY, sw::Surface::TOP);
+       negX->copyCubeEdge(sw::Surface::BOTTOM, negY, sw::Surface::LEFT);
+       negY->copyCubeEdge(sw::Surface::BOTTOM, negZ, sw::Surface::BOTTOM);
+       negZ->copyCubeEdge(sw::Surface::BOTTOM, negY, sw::Surface::BOTTOM);
+
+       posX->copyCubeEdge(sw::Surface::TOP, posY, sw::Surface::RIGHT);
+       posY->copyCubeEdge(sw::Surface::TOP, negZ, sw::Surface::TOP);
+       posZ->copyCubeEdge(sw::Surface::TOP, posY, sw::Surface::BOTTOM);
+       negX->copyCubeEdge(sw::Surface::TOP, posY, sw::Surface::LEFT);
+       negY->copyCubeEdge(sw::Surface::TOP, posZ, sw::Surface::BOTTOM);
+       negZ->copyCubeEdge(sw::Surface::TOP, posY, sw::Surface::TOP);
+
+       // Copy left / right after top and bottom are done.
+       // The corner colors will be computed assuming top / bottom are already set.
+       posX->copyCubeEdge(sw::Surface::RIGHT, negZ, sw::Surface::LEFT);
+       posY->copyCubeEdge(sw::Surface::RIGHT, posX, sw::Surface::TOP);
+       posZ->copyCubeEdge(sw::Surface::RIGHT, posX, sw::Surface::LEFT);
+       negX->copyCubeEdge(sw::Surface::RIGHT, posZ, sw::Surface::LEFT);
+       negY->copyCubeEdge(sw::Surface::RIGHT, posX, sw::Surface::BOTTOM);
+       negZ->copyCubeEdge(sw::Surface::RIGHT, negX, sw::Surface::LEFT);
+
+       posX->copyCubeEdge(sw::Surface::LEFT, posZ, sw::Surface::RIGHT);
+       posY->copyCubeEdge(sw::Surface::LEFT, negX, sw::Surface::TOP);
+       posZ->copyCubeEdge(sw::Surface::LEFT, negX, sw::Surface::RIGHT);
+       negX->copyCubeEdge(sw::Surface::LEFT, negZ, sw::Surface::RIGHT);
+       negY->copyCubeEdge(sw::Surface::LEFT, negX, sw::Surface::BOTTOM);
+       negZ->copyCubeEdge(sw::Surface::LEFT, posX, sw::Surface::RIGHT);
+}
+
 bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
 {
        return IsCompressed(getFormat(target, level), egl::getClientVersion());
index 143c51e..d5e0c80 100644 (file)
@@ -237,6 +237,7 @@ public:
        void releaseTexImage() override;
 
        void generateMipmaps() override;
+       void updateBorders(int level);
 
        Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer) override;
        egl::Image *getRenderTarget(GLenum target, unsigned int level) override;
index 2ec5183..3533d25 100644 (file)
@@ -3554,6 +3554,81 @@ namespace sw
                internal.write(x, y, z, color);
        }
 
+       void Surface::copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge)
+       {
+               Surface *dst = this;
+
+               // Figure out if the edges to be copied in reverse order respectively from one another
+               // The copy should be reversed whenever the same edges are contiguous or if we're
+               // copying top <-> right or bottom <-> left. This is explained by the layout, which is:
+               //
+               //      | +y |
+               // | -x | +z | +x | -z |
+               //      | -y |
+
+               bool reverse = (srcEdge == dstEdge) ||
+                              ((srcEdge == TOP) && (dstEdge == RIGHT)) ||
+                              ((srcEdge == RIGHT) && (dstEdge == TOP)) ||
+                              ((srcEdge == BOTTOM) && (dstEdge == LEFT)) ||
+                              ((srcEdge == LEFT) && (dstEdge == BOTTOM));
+
+               int srcBytes = src->bytes(src->Surface::getInternalFormat());
+               int srcPitch = src->getInternalPitchB();
+               int dstBytes = dst->bytes(dst->Surface::getInternalFormat());
+               int dstPitch = dst->getInternalPitchB();
+
+               int srcW = src->getWidth();
+               int srcH = src->getHeight();
+               int dstW = dst->getWidth();
+               int dstH = dst->getHeight();
+
+               ASSERT(srcW == srcH && dstW == dstH && srcW == dstW && srcBytes == dstBytes);
+
+               // Src is expressed in the regular [0, width-1], [0, height-1] space
+               int srcDelta = ((srcEdge == TOP) || (srcEdge == BOTTOM)) ? srcBytes : srcPitch;
+               int srcStart = ((srcEdge == BOTTOM) ? srcPitch * (srcH - 1) : ((srcEdge == RIGHT) ? srcBytes * (srcW - 1) : 0));
+
+               // Dst contains borders, so it is expressed in the [-1, width+1], [-1, height+1] space
+               int dstDelta = (((dstEdge == TOP) || (dstEdge == BOTTOM)) ? dstBytes : dstPitch) * (reverse ? -1 : 1);
+               int dstStart = ((dstEdge == BOTTOM) ? dstPitch * (dstH + 1) : ((dstEdge == RIGHT) ? dstBytes * (dstW + 1) : 0)) + (reverse ? dstW * -dstDelta : dstDelta);
+
+               char *srcBuf = (char*)src->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PRIVATE) + srcStart;
+               char *dstBuf = (char*)dst->lockInternal(-1, -1, 0, sw::LOCK_READWRITE, sw::PRIVATE) + dstStart;
+
+               for(int i = 0; i < srcW; ++i, dstBuf += dstDelta, srcBuf += srcDelta)
+               {
+                       memcpy(dstBuf, srcBuf, srcBytes);
+               }
+
+               if(dstEdge == LEFT || dstEdge == RIGHT)
+               {
+                       // TOP and BOTTOM are already set, let's average out the corners
+                       int x0 = (dstEdge == RIGHT) ? dstW : -1;
+                       int y0 = -1;
+                       int x1 = (dstEdge == RIGHT) ? dstW - 1 : 0;
+                       int y1 = 0;
+                       dst->computeCubeCorner(x0, y0, x1, y1);
+                       y0 = dstH;
+                       y1 = dstH - 1;
+                       dst->computeCubeCorner(x0, y0, x1, y1);
+               }
+
+               src->unlockInternal();
+               dst->unlockInternal();
+       }
+
+       void Surface::computeCubeCorner(int x0, int y0, int x1, int y1)
+       {
+               ASSERT(internal.lock != LOCK_UNLOCKED);
+
+               sw::Color<float> color = internal.read(x0, y1);
+               color += internal.read(x1, y0);
+               color += internal.read(x1, y1);
+               color *= (1.0f / 3.0f);
+
+               internal.write(x0, y0, color);
+       }
+
        bool Surface::hasStencil() const
        {
                return isStencil(external.format);
index 3a6e59e..4de2b33 100644 (file)
@@ -317,6 +317,10 @@ namespace sw
                void copyInternal(const Surface* src, int x, int y, float srcX, float srcY, bool filter);
                void copyInternal(const Surface* src, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter);
 
+               enum Edge { TOP, BOTTOM, RIGHT, LEFT };
+               void copyCubeEdge(Edge dstEdge, Surface *src, Edge srcEdge);
+               void computeCubeCorner(int x0, int y0, int x1, int y1);
+
                bool hasStencil() const;
                bool hasDepth() const;
                bool hasPalette() const;