Commit a76a1bfd by Alexis Hetu Committed by Nicolas Capens

Functionality to update borders of cube textures.

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/8209Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 9c6d5222
...@@ -1246,6 +1246,52 @@ bool TextureCubeMap::isMipmapCubeComplete() const ...@@ -1246,6 +1246,52 @@ bool TextureCubeMap::isMipmapCubeComplete() const
return true; 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 bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
{ {
return IsCompressed(getFormat(target, level), egl::getClientVersion()); return IsCompressed(getFormat(target, level), egl::getClientVersion());
......
...@@ -237,6 +237,7 @@ public: ...@@ -237,6 +237,7 @@ public:
void releaseTexImage() override; void releaseTexImage() override;
void generateMipmaps() override; void generateMipmaps() override;
void updateBorders(int level);
Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer) override; Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer) override;
egl::Image *getRenderTarget(GLenum target, unsigned int level) override; egl::Image *getRenderTarget(GLenum target, unsigned int level) override;
......
...@@ -3554,6 +3554,81 @@ namespace sw ...@@ -3554,6 +3554,81 @@ namespace sw
internal.write(x, y, z, color); 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 bool Surface::hasStencil() const
{ {
return isStencil(external.format); return isStencil(external.format);
......
...@@ -317,6 +317,10 @@ namespace sw ...@@ -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, 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); 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 hasStencil() const;
bool hasDepth() const; bool hasDepth() const;
bool hasPalette() const; bool hasPalette() const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment