Commit 9c6d5222 by Alexis Hetu Committed by Nicolas Capens

Add support for borders around textures.

Borders are required to support seamless cubemap sampling. Subsequent patches will fill the borders with pixels from adjacent cube faces. The border is expressed in pixels and is added on all edges, resulting in an image of dimensions (width + 2 * border) x (height + 2 * border). The surface still exposes dimensions of width x height through the API and points to the same pixel when locked. Change-Id: I06d5121267ce1a2c50e628490d8690de71bfeb08 Reviewed-on: https://swiftshader-review.googlesource.com/8208Tested-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 f8b827ef
...@@ -227,7 +227,7 @@ namespace D3D8 ...@@ -227,7 +227,7 @@ namespace D3D8
desc->Type = D3DRTYPE_SURFACE; desc->Type = D3DRTYPE_SURFACE;
desc->Height = height; desc->Height = height;
desc->Width = width; desc->Width = width;
desc->Size = size(getWidth(), getHeight(), getDepth(), getExternalFormat()); desc->Size = size(getWidth(), getHeight(), getDepth(), 0, getExternalFormat());
desc->MultiSampleType = multiSample; desc->MultiSampleType = multiSample;
desc->Usage = usage; desc->Usage = usage;
...@@ -285,6 +285,6 @@ namespace D3D8 ...@@ -285,6 +285,6 @@ namespace D3D8
unsigned int Direct3DSurface8::memoryUsage(int width, int height, D3DFORMAT format) unsigned int Direct3DSurface8::memoryUsage(int width, int height, D3DFORMAT format)
{ {
return Surface::size(width, height, 1, translateFormat(format)); return Surface::size(width, height, 1, 0, translateFormat(format));
} }
} }
...@@ -144,8 +144,8 @@ namespace D3D8 ...@@ -144,8 +144,8 @@ namespace D3D8
return INVALIDCALL(); return INVALIDCALL();
} }
lockedVolume->RowPitch = pitchB(getWidth(), getExternalFormat(), false); lockedVolume->RowPitch = pitchB(getWidth(), 0, getExternalFormat(), false);
lockedVolume->SlicePitch = sliceB(getWidth(), getHeight(), getExternalFormat(), false); lockedVolume->SlicePitch = sliceB(getWidth(), getHeight(), 0, getExternalFormat(), false);
sw::Lock lock = sw::LOCK_READWRITE; sw::Lock lock = sw::LOCK_READWRITE;
...@@ -194,6 +194,6 @@ namespace D3D8 ...@@ -194,6 +194,6 @@ namespace D3D8
unsigned int Direct3DVolume8::memoryUsage(int width, int height, int depth, D3DFORMAT format) unsigned int Direct3DVolume8::memoryUsage(int width, int height, int depth, D3DFORMAT format)
{ {
return Surface::size(width, height, depth, translateFormat(format)); return Surface::size(width, height, depth, 0, translateFormat(format));
} }
} }
...@@ -2660,7 +2660,7 @@ namespace D3D9 ...@@ -2660,7 +2660,7 @@ namespace D3D9
void *bitmap = cursorSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); void *bitmap = cursorSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
delete cursor; delete cursor;
cursor = sw::Surface::create(0, width, height, 1, sw::FORMAT_A8R8G8B8, false, false); cursor = sw::Surface::create(nullptr, width, height, 1, 0, sw::FORMAT_A8R8G8B8, false, false);
void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC); void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
memcpy(buffer, bitmap, width * height * sizeof(unsigned int)); memcpy(buffer, bitmap, width * height * sizeof(unsigned int));
...@@ -2674,7 +2674,7 @@ namespace D3D9 ...@@ -2674,7 +2674,7 @@ namespace D3D9
} }
else else
{ {
sw::FrameBuffer::setCursorImage(0); sw::FrameBuffer::setCursorImage(nullptr);
} }
sw::FrameBuffer::setCursorOrigin(x0, y0); sw::FrameBuffer::setCursorOrigin(x0, y0);
......
...@@ -76,7 +76,8 @@ namespace D3D9 ...@@ -76,7 +76,8 @@ namespace D3D9
return (pool != D3DPOOL_DEFAULT) || (usage & D3DUSAGE_DYNAMIC) || lockableOverride; return (pool != D3DPOOL_DEFAULT) || (usage & D3DUSAGE_DYNAMIC) || lockableOverride;
} }
Direct3DSurface9::Direct3DSurface9(Direct3DDevice9 *device, Unknown *container, int width, int height, D3DFORMAT format, D3DPOOL pool, D3DMULTISAMPLE_TYPE multiSample, unsigned int quality, bool lockableOverride, unsigned long usage) : Direct3DResource9(device, D3DRTYPE_SURFACE, pool, memoryUsage(width, height, format)), Surface(getParentResource(container), width, height, sampleCount(multiSample, quality), translateFormat(format), isLockable(pool, usage, lockableOverride), (usage & D3DUSAGE_RENDERTARGET) || (usage & D3DUSAGE_DEPTHSTENCIL)), container(container), width(width), height(height), format(format), pool(pool), multiSample(multiSample), quality(quality), lockable(isLockable(pool, usage, lockableOverride)), usage(usage) Direct3DSurface9::Direct3DSurface9(Direct3DDevice9 *device, Unknown *container, int width, int height, D3DFORMAT format, D3DPOOL pool, D3DMULTISAMPLE_TYPE multiSample, unsigned int quality, bool lockableOverride, unsigned long usage)
: Direct3DResource9(device, D3DRTYPE_SURFACE, pool, memoryUsage(width, height, format)), Surface(getParentResource(container), width, height, sampleCount(multiSample, quality), 0, translateFormat(format), isLockable(pool, usage, lockableOverride), (usage & D3DUSAGE_RENDERTARGET) || (usage & D3DUSAGE_DEPTHSTENCIL)), container(container), width(width), height(height), format(format), pool(pool), multiSample(multiSample), quality(quality), lockable(isLockable(pool, usage, lockableOverride)), usage(usage)
{ {
parentTexture = dynamic_cast<Direct3DBaseTexture9*>(container); parentTexture = dynamic_cast<Direct3DBaseTexture9*>(container);
} }
...@@ -412,6 +413,6 @@ namespace D3D9 ...@@ -412,6 +413,6 @@ namespace D3D9
unsigned int Direct3DSurface9::memoryUsage(int width, int height, D3DFORMAT format) unsigned int Direct3DSurface9::memoryUsage(int width, int height, D3DFORMAT format)
{ {
return Surface::size(width, height, 1, translateFormat(format)); return Surface::size(width, height, 1, 0, translateFormat(format));
} }
} }
...@@ -30,7 +30,8 @@ namespace D3D9 ...@@ -30,7 +30,8 @@ namespace D3D9
return (pool != D3DPOOL_DEFAULT) || (usage & D3DUSAGE_DYNAMIC); return (pool != D3DPOOL_DEFAULT) || (usage & D3DUSAGE_DYNAMIC);
} }
Direct3DVolume9::Direct3DVolume9(Direct3DDevice9 *device, Direct3DVolumeTexture9 *container, int width, int height, int depth, D3DFORMAT format, D3DPOOL pool, unsigned long usage) : device(device), Surface(container->getResource(), width, height, depth, translateFormat(format), isLockable(pool, usage), false), container(container), width(width), height(height), depth(depth), format(format), pool(pool), lockable(isLockable(pool, usage)), usage(usage) Direct3DVolume9::Direct3DVolume9(Direct3DDevice9 *device, Direct3DVolumeTexture9 *container, int width, int height, int depth, D3DFORMAT format, D3DPOOL pool, unsigned long usage)
: device(device), Surface(container->getResource(), width, height, depth, 0, translateFormat(format), isLockable(pool, usage), false), container(container), width(width), height(height), depth(depth), format(format), pool(pool), lockable(isLockable(pool, usage)), usage(usage)
{ {
resource = new Direct3DResource9(device, D3DRTYPE_VOLUME, pool, memoryUsage(width, height, depth, format)); resource = new Direct3DResource9(device, D3DRTYPE_VOLUME, pool, memoryUsage(width, height, depth, format));
resource->bind(); resource->bind();
...@@ -229,6 +230,6 @@ namespace D3D9 ...@@ -229,6 +230,6 @@ namespace D3D9
unsigned int Direct3DVolume9::memoryUsage(int width, int height, int depth, D3DFORMAT format) unsigned int Direct3DVolume9::memoryUsage(int width, int height, int depth, D3DFORMAT format)
{ {
return Surface::size(width, height, depth, translateFormat(format)); return Surface::size(width, height, depth, 0, translateFormat(format));
} }
} }
...@@ -1232,8 +1232,8 @@ namespace egl ...@@ -1232,8 +1232,8 @@ namespace egl
public: public:
ImageImplementation(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type) ImageImplementation(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
: Image(parentTexture, width, height, format, type) {} : Image(parentTexture, width, height, format, type) {}
ImageImplementation(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type) ImageImplementation(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLenum format, GLenum type)
: Image(parentTexture, width, height, depth, format, type) {} : Image(parentTexture, width, height, depth, border, format, type) {}
ImageImplementation(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP) ImageImplementation(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
: Image(width, height, format, type, pitchP) {} : Image(width, height, format, type, pitchP) {}
ImageImplementation(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable) ImageImplementation(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable)
...@@ -1265,9 +1265,9 @@ namespace egl ...@@ -1265,9 +1265,9 @@ namespace egl
return new ImageImplementation(parentTexture, width, height, format, type); return new ImageImplementation(parentTexture, width, height, format, type);
} }
Image *Image::create(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type) Image *Image::create(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLenum format, GLenum type)
{ {
return new ImageImplementation(parentTexture, width, height, depth, format, type); return new ImageImplementation(parentTexture, width, height, depth, border, format, type);
} }
Image *Image::create(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP) Image *Image::create(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
......
...@@ -52,7 +52,7 @@ class [[clang::lto_visibility_public]] Image : public sw::Surface, public gl::Ob ...@@ -52,7 +52,7 @@ class [[clang::lto_visibility_public]] Image : public sw::Surface, public gl::Ob
protected: protected:
// 2D texture image // 2D texture image
Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type) Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
: sw::Surface(parentTexture->getResource(), width, height, 1, SelectInternalFormat(format, type), true, true), : sw::Surface(parentTexture->getResource(), width, height, 1, 0, SelectInternalFormat(format, type), true, true),
width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(1), width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(1),
parentTexture(parentTexture) parentTexture(parentTexture)
{ {
...@@ -61,9 +61,9 @@ protected: ...@@ -61,9 +61,9 @@ protected:
parentTexture->addRef(); parentTexture->addRef();
} }
// 3D texture image // 3D/Cube texture image
Image(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type) Image(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLenum format, GLenum type)
: sw::Surface(parentTexture->getResource(), width, height, depth, SelectInternalFormat(format, type), true, true), : sw::Surface(parentTexture->getResource(), width, height, depth, border, SelectInternalFormat(format, type), true, true),
width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(depth), width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(depth),
parentTexture(parentTexture) parentTexture(parentTexture)
{ {
...@@ -74,7 +74,7 @@ protected: ...@@ -74,7 +74,7 @@ protected:
// Native EGL image // Native EGL image
Image(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP) Image(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
: sw::Surface(nullptr, width, height, 1, SelectInternalFormat(format, type), true, true, pitchP), : sw::Surface(nullptr, width, height, 1, 0, SelectInternalFormat(format, type), true, true, pitchP),
width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(1), width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(1),
parentTexture(nullptr) parentTexture(nullptr)
{ {
...@@ -84,7 +84,7 @@ protected: ...@@ -84,7 +84,7 @@ protected:
// Render target // Render target
Image(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable) Image(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable)
: sw::Surface(nullptr, width, height, multiSampleDepth, internalFormat, lockable, true), : sw::Surface(nullptr, width, height, multiSampleDepth, 0, internalFormat, lockable, true),
width(width), height(height), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), internalFormat(internalFormat), depth(multiSampleDepth), width(width), height(height), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), internalFormat(internalFormat), depth(multiSampleDepth),
parentTexture(nullptr) parentTexture(nullptr)
{ {
...@@ -96,8 +96,8 @@ public: ...@@ -96,8 +96,8 @@ public:
// 2D texture image // 2D texture image
static Image *create(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type); static Image *create(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type);
// 3D texture image // 3D/Cube texture image
static Image *create(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type); static Image *create(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLenum format, GLenum type);
// Native EGL image // Native EGL image
static Image *create(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP); static Image *create(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP);
......
...@@ -39,14 +39,14 @@ namespace gl ...@@ -39,14 +39,14 @@ namespace gl
Image::Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type) Image::Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
: parentTexture(parentTexture), width(width), height(height), format(format), type(type) : parentTexture(parentTexture), width(width), height(height), format(format), type(type)
, internalFormat(selectInternalFormat(format, type)), multiSampleDepth(1) , internalFormat(selectInternalFormat(format, type)), multiSampleDepth(1)
, sw::Surface(getParentResource(parentTexture), width, height, 1, selectInternalFormat(format, type), true, true) , sw::Surface(getParentResource(parentTexture), width, height, 1, 0, selectInternalFormat(format, type), true, true)
{ {
referenceCount = 1; referenceCount = 1;
} }
Image::Image(Texture *parentTexture, GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable, bool renderTarget) Image::Image(Texture *parentTexture, GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable, bool renderTarget)
: parentTexture(parentTexture), width(width), height(height), internalFormat(internalFormat), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), multiSampleDepth(multiSampleDepth) : parentTexture(parentTexture), width(width), height(height), internalFormat(internalFormat), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), multiSampleDepth(multiSampleDepth)
, sw::Surface(getParentResource(parentTexture), width, height, multiSampleDepth, internalFormat, lockable, renderTarget) , sw::Surface(getParentResource(parentTexture), width, height, multiSampleDepth, 0, internalFormat, lockable, renderTarget)
{ {
referenceCount = 1; referenceCount = 1;
} }
......
...@@ -1128,7 +1128,8 @@ void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum forma ...@@ -1128,7 +1128,8 @@ void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum forma
} }
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[face][level] = egl::Image::create(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE); int border = (egl::getClientVersion() >= 3) ? 1 : 0;
image[face][level] = egl::Image::create(this, width, height, 1, border, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[face][level]) if(!image[face][level])
{ {
...@@ -1269,7 +1270,8 @@ void TextureCubeMap::setImage(egl::Context *context, GLenum target, GLint level, ...@@ -1269,7 +1270,8 @@ void TextureCubeMap::setImage(egl::Context *context, GLenum target, GLint level,
image[face][level]->release(); image[face][level]->release();
} }
image[face][level] = egl::Image::create(this, width, height, format, type); int border = (egl::getClientVersion() >= 3) ? 1 : 0;
image[face][level] = egl::Image::create(this, width, height, 1, border, format, type);
if(!image[face][level]) if(!image[face][level])
{ {
...@@ -1297,7 +1299,8 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint ...@@ -1297,7 +1299,8 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint
} }
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[face][level] = egl::Image::create(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE); int border = (egl::getClientVersion() >= 3) ? 1 : 0;
image[face][level] = egl::Image::create(this, width, height, 1, border, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[face][level]) if(!image[face][level])
{ {
...@@ -1391,7 +1394,8 @@ void TextureCubeMap::generateMipmaps() ...@@ -1391,7 +1394,8 @@ void TextureCubeMap::generateMipmaps()
image[f][i]->release(); image[f][i]->release();
} }
image[f][i] = egl::Image::create(this, std::max(image[0][0]->getWidth() >> i, 1), std::max(image[0][0]->getHeight() >> i, 1), image[0][0]->getFormat(), image[0][0]->getType()); int border = (egl::getClientVersion() >= 3) ? 1 : 0;
image[f][i] = egl::Image::create(this, std::max(image[0][0]->getWidth() >> i, 1), std::max(image[0][0]->getHeight() >> i, 1), 1, border, image[0][0]->getFormat(), image[0][0]->getType());
if(!image[f][i]) if(!image[f][i])
{ {
...@@ -1592,7 +1596,7 @@ void Texture3D::setImage(egl::Context *context, GLint level, GLsizei width, GLsi ...@@ -1592,7 +1596,7 @@ void Texture3D::setImage(egl::Context *context, GLint level, GLsizei width, GLsi
image[level]->release(); image[level]->release();
} }
image[level] = egl::Image::create(this, width, height, depth, format, type); image[level] = egl::Image::create(this, width, height, depth, 0, format, type);
if(!image[level]) if(!image[level])
{ {
...@@ -1615,7 +1619,7 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL ...@@ -1615,7 +1619,7 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL
} }
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[level] = egl::Image::create(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE); image[level] = egl::Image::create(this, width, height, depth, 0, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[level]) if(!image[level])
{ {
...@@ -1651,7 +1655,7 @@ void Texture3D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z, ...@@ -1651,7 +1655,7 @@ void Texture3D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z,
} }
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[level] = egl::Image::create(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE); image[level] = egl::Image::create(this, width, height, depth, 0, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[level]) if(!image[level])
{ {
...@@ -1829,7 +1833,7 @@ void Texture3D::generateMipmaps() ...@@ -1829,7 +1833,7 @@ void Texture3D::generateMipmaps()
image[i]->release(); image[i]->release();
} }
image[i] = egl::Image::create(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()); image[i] = egl::Image::create(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), std::max(image[0]->getDepth() >> i, 1), 0, image[0]->getFormat(), image[0]->getType());
if(!image[i]) if(!image[i])
{ {
...@@ -1928,7 +1932,7 @@ void Texture2DArray::generateMipmaps() ...@@ -1928,7 +1932,7 @@ void Texture2DArray::generateMipmaps()
GLsizei w = std::max(image[0]->getWidth() >> i, 1); GLsizei w = std::max(image[0]->getWidth() >> i, 1);
GLsizei h = std::max(image[0]->getHeight() >> i, 1); GLsizei h = std::max(image[0]->getHeight() >> i, 1);
image[i] = egl::Image::create(this, w, h, depth, image[0]->getFormat(), image[0]->getType()); image[i] = egl::Image::create(this, w, h, depth, 0, image[0]->getFormat(), image[0]->getType());
if(!image[i]) if(!image[i])
{ {
......
...@@ -52,14 +52,14 @@ namespace sw ...@@ -52,14 +52,14 @@ namespace sw
void Surface::Buffer::write(int x, int y, int z, const Color<float> &color) void Surface::Buffer::write(int x, int y, int z, const Color<float> &color)
{ {
void *element = (unsigned char*)buffer + x * bytes + y * pitchB + z * sliceB; void *element = (unsigned char*)buffer + (x + border) * bytes + (y + border) * pitchB + z * sliceB;
write(element, color); write(element, color);
} }
void Surface::Buffer::write(int x, int y, const Color<float> &color) void Surface::Buffer::write(int x, int y, const Color<float> &color)
{ {
void *element = (unsigned char*)buffer + x * bytes + y * pitchB; void *element = (unsigned char*)buffer + (x + border) * bytes + (y + border) * pitchB;
write(element, color); write(element, color);
} }
...@@ -370,14 +370,14 @@ namespace sw ...@@ -370,14 +370,14 @@ namespace sw
Color<float> Surface::Buffer::read(int x, int y, int z) const Color<float> Surface::Buffer::read(int x, int y, int z) const
{ {
void *element = (unsigned char*)buffer + x * bytes + y * pitchB + z * sliceB; void *element = (unsigned char*)buffer + (x + border) * bytes + (y + border) * pitchB + z * sliceB;
return read(element); return read(element);
} }
Color<float> Surface::Buffer::read(int x, int y) const Color<float> Surface::Buffer::read(int x, int y) const
{ {
void *element = (unsigned char*)buffer + x * bytes + y * pitchB; void *element = (unsigned char*)buffer + (x + border) * bytes + (y + border) * pitchB;
return read(element); return read(element);
} }
...@@ -1088,6 +1088,9 @@ namespace sw ...@@ -1088,6 +1088,9 @@ namespace sw
if(buffer) if(buffer)
{ {
x += border;
y += border;
switch(format) switch(format)
{ {
#if S3TC_SUPPORT #if S3TC_SUPPORT
...@@ -1172,8 +1175,8 @@ namespace sw ...@@ -1172,8 +1175,8 @@ namespace sw
public: public:
SurfaceImplementation(int width, int height, int depth, Format format, void *pixels, int pitch, int slice) SurfaceImplementation(int width, int height, int depth, Format format, void *pixels, int pitch, int slice)
: Surface(width, height, depth, format, pixels, pitch, slice) {} : Surface(width, height, depth, format, pixels, pitch, slice) {}
SurfaceImplementation(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchP = 0) SurfaceImplementation(Resource *texture, int width, int height, int depth, int border, Format format, bool lockable, bool renderTarget, int pitchP = 0)
: Surface(texture, width, height, depth, format, lockable, renderTarget, pitchP) {} : Surface(texture, width, height, depth, border, format, lockable, renderTarget, pitchP) {}
~SurfaceImplementation() override {}; ~SurfaceImplementation() override {};
void *lockInternal(int x, int y, int z, Lock lock, Accessor client) override void *lockInternal(int x, int y, int z, Lock lock, Accessor client) override
...@@ -1192,9 +1195,9 @@ namespace sw ...@@ -1192,9 +1195,9 @@ namespace sw
return new SurfaceImplementation(width, height, depth, format, pixels, pitch, slice); return new SurfaceImplementation(width, height, depth, format, pixels, pitch, slice);
} }
Surface *Surface::create(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchPprovided) Surface *Surface::create(Resource *texture, int width, int height, int depth, int border, Format format, bool lockable, bool renderTarget, int pitchPprovided)
{ {
return new SurfaceImplementation(texture, width, height, depth, format, lockable, renderTarget, pitchPprovided); return new SurfaceImplementation(texture, width, height, depth, border, format, lockable, renderTarget, pitchPprovided);
} }
Surface::Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice) : lockable(true), renderTarget(false) Surface::Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice) : lockable(true), renderTarget(false)
...@@ -1214,6 +1217,7 @@ namespace sw ...@@ -1214,6 +1217,7 @@ namespace sw
external.pitchP = external.bytes ? pitch / external.bytes : 0; external.pitchP = external.bytes ? pitch / external.bytes : 0;
external.sliceB = slice; external.sliceB = slice;
external.sliceP = external.bytes ? slice / external.bytes : 0; external.sliceP = external.bytes ? slice / external.bytes : 0;
external.border = 0;
external.lock = LOCK_UNLOCKED; external.lock = LOCK_UNLOCKED;
external.dirty = true; external.dirty = true;
...@@ -1223,10 +1227,11 @@ namespace sw ...@@ -1223,10 +1227,11 @@ namespace sw
internal.depth = depth; internal.depth = depth;
internal.format = selectInternalFormat(format); internal.format = selectInternalFormat(format);
internal.bytes = bytes(internal.format); internal.bytes = bytes(internal.format);
internal.pitchB = pitchB(internal.width, internal.format, false); internal.pitchB = pitchB(internal.width, 0, internal.format, false);
internal.pitchP = pitchP(internal.width, internal.format, false); internal.pitchP = pitchP(internal.width, 0, internal.format, false);
internal.sliceB = sliceB(internal.width, internal.height, internal.format, false); internal.sliceB = sliceB(internal.width, internal.height, 0, internal.format, false);
internal.sliceP = sliceP(internal.width, internal.height, internal.format, false); internal.sliceP = sliceP(internal.width, internal.height, 0, internal.format, false);
internal.border = 0;
internal.lock = LOCK_UNLOCKED; internal.lock = LOCK_UNLOCKED;
internal.dirty = false; internal.dirty = false;
...@@ -1236,10 +1241,11 @@ namespace sw ...@@ -1236,10 +1241,11 @@ namespace sw
stencil.depth = depth; stencil.depth = depth;
stencil.format = FORMAT_S8; stencil.format = FORMAT_S8;
stencil.bytes = bytes(stencil.format); stencil.bytes = bytes(stencil.format);
stencil.pitchB = pitchB(stencil.width, stencil.format, false); stencil.pitchB = pitchB(stencil.width, 0, stencil.format, false);
stencil.pitchP = pitchP(stencil.width, stencil.format, false); stencil.pitchP = pitchP(stencil.width, 0, stencil.format, false);
stencil.sliceB = sliceB(stencil.width, stencil.height, stencil.format, false); stencil.sliceB = sliceB(stencil.width, stencil.height, 0, stencil.format, false);
stencil.sliceP = sliceP(stencil.width, stencil.height, stencil.format, false); stencil.sliceP = sliceP(stencil.width, stencil.height, 0, stencil.format, false);
stencil.border = 0;
stencil.lock = LOCK_UNLOCKED; stencil.lock = LOCK_UNLOCKED;
stencil.dirty = false; stencil.dirty = false;
...@@ -1247,7 +1253,7 @@ namespace sw ...@@ -1247,7 +1253,7 @@ namespace sw
paletteUsed = 0; paletteUsed = 0;
} }
Surface::Surface(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchPprovided) : lockable(lockable), renderTarget(renderTarget) Surface::Surface(Resource *texture, int width, int height, int depth, int border, Format format, bool lockable, bool renderTarget, int pitchPprovided) : lockable(lockable), renderTarget(renderTarget)
{ {
resource = texture ? texture : new Resource(0); resource = texture ? texture : new Resource(0);
hasParent = texture != 0; hasParent = texture != 0;
...@@ -1260,10 +1266,11 @@ namespace sw ...@@ -1260,10 +1266,11 @@ namespace sw
external.depth = depth; external.depth = depth;
external.format = format; external.format = format;
external.bytes = bytes(external.format); external.bytes = bytes(external.format);
external.pitchB = pitchB(external.width, external.format, renderTarget && !texture); external.pitchB = pitchB(external.width, 0, external.format, renderTarget && !texture);
external.pitchP = pitchP(external.width, external.format, renderTarget && !texture); external.pitchP = pitchP(external.width, 0, external.format, renderTarget && !texture);
external.sliceB = sliceB(external.width, external.height, external.format, renderTarget && !texture); external.sliceB = sliceB(external.width, external.height, 0, external.format, renderTarget && !texture);
external.sliceP = sliceP(external.width, external.height, external.format, renderTarget && !texture); external.sliceP = sliceP(external.width, external.height, 0, external.format, renderTarget && !texture);
external.border = 0;
external.lock = LOCK_UNLOCKED; external.lock = LOCK_UNLOCKED;
external.dirty = false; external.dirty = false;
...@@ -1273,10 +1280,11 @@ namespace sw ...@@ -1273,10 +1280,11 @@ namespace sw
internal.depth = depth; internal.depth = depth;
internal.format = selectInternalFormat(format); internal.format = selectInternalFormat(format);
internal.bytes = bytes(internal.format); internal.bytes = bytes(internal.format);
internal.pitchB = !pitchPprovided ? pitchB(internal.width, internal.format, renderTarget) : pitchPprovided * internal.bytes; internal.pitchB = !pitchPprovided ? pitchB(internal.width, border, internal.format, renderTarget) : pitchPprovided * internal.bytes;
internal.pitchP = !pitchPprovided ? pitchP(internal.width, internal.format, renderTarget) : pitchPprovided; internal.pitchP = !pitchPprovided ? pitchP(internal.width, border, internal.format, renderTarget) : pitchPprovided;
internal.sliceB = sliceB(internal.width, internal.height, internal.format, renderTarget); internal.sliceB = sliceB(internal.width, internal.height, border, internal.format, renderTarget);
internal.sliceP = sliceP(internal.width, internal.height, internal.format, renderTarget); internal.sliceP = sliceP(internal.width, internal.height, border, internal.format, renderTarget);
internal.border = border;
internal.lock = LOCK_UNLOCKED; internal.lock = LOCK_UNLOCKED;
internal.dirty = false; internal.dirty = false;
...@@ -1286,10 +1294,11 @@ namespace sw ...@@ -1286,10 +1294,11 @@ namespace sw
stencil.depth = depth; stencil.depth = depth;
stencil.format = FORMAT_S8; stencil.format = FORMAT_S8;
stencil.bytes = bytes(stencil.format); stencil.bytes = bytes(stencil.format);
stencil.pitchB = pitchB(stencil.width, stencil.format, renderTarget); stencil.pitchB = pitchB(stencil.width, 0, stencil.format, renderTarget);
stencil.pitchP = pitchP(stencil.width, stencil.format, renderTarget); stencil.pitchP = pitchP(stencil.width, 0, stencil.format, renderTarget);
stencil.sliceB = sliceB(stencil.width, stencil.height, stencil.format, renderTarget); stencil.sliceB = sliceB(stencil.width, stencil.height, 0, stencil.format, renderTarget);
stencil.sliceP = sliceP(stencil.width, stencil.height, stencil.format, renderTarget); stencil.sliceP = sliceP(stencil.width, stencil.height, 0, stencil.format, renderTarget);
stencil.border = 0;
stencil.lock = LOCK_UNLOCKED; stencil.lock = LOCK_UNLOCKED;
stencil.dirty = false; stencil.dirty = false;
...@@ -1337,7 +1346,7 @@ namespace sw ...@@ -1337,7 +1346,7 @@ namespace sw
} }
else else
{ {
external.buffer = allocateBuffer(external.width, external.height, external.depth, external.format); external.buffer = allocateBuffer(external.width, external.height, external.depth, external.border, external.format);
} }
} }
...@@ -1389,7 +1398,7 @@ namespace sw ...@@ -1389,7 +1398,7 @@ namespace sw
} }
else else
{ {
internal.buffer = allocateBuffer(internal.width, internal.height, internal.depth, internal.format); internal.buffer = allocateBuffer(internal.width, internal.height, internal.depth, internal.border, internal.format);
} }
} }
...@@ -1464,7 +1473,7 @@ namespace sw ...@@ -1464,7 +1473,7 @@ namespace sw
if(!stencil.buffer) if(!stencil.buffer)
{ {
stencil.buffer = allocateBuffer(stencil.width, stencil.height, stencil.depth, stencil.format); stencil.buffer = allocateBuffer(stencil.width, stencil.height, stencil.depth, stencil.border, stencil.format);
} }
return stencil.lockRect(x, y, front, LOCK_READWRITE); // FIXME return stencil.lockRect(x, y, front, LOCK_READWRITE); // FIXME
...@@ -1640,8 +1649,10 @@ namespace sw ...@@ -1640,8 +1649,10 @@ namespace sw
return 0; return 0;
} }
int Surface::pitchB(int width, Format format, bool target) int Surface::pitchB(int width, int border, Format format, bool target)
{ {
width += 2 * border;
if(target || isDepth(format) || isStencil(format)) if(target || isDepth(format) || isStencil(format))
{ {
width = align(width, 2); width = align(width, 2);
...@@ -1716,15 +1727,17 @@ namespace sw ...@@ -1716,15 +1727,17 @@ namespace sw
} }
} }
int Surface::pitchP(int width, Format format, bool target) int Surface::pitchP(int width, int border, Format format, bool target)
{ {
int B = bytes(format); int B = bytes(format);
return B > 0 ? pitchB(width, format, target) / B : 0; return B > 0 ? pitchB(width, border, format, target) / B : 0;
} }
int Surface::sliceB(int width, int height, Format format, bool target) int Surface::sliceB(int width, int height, int border, Format format, bool target)
{ {
height += 2 * border;
if(target || isDepth(format) || isStencil(format)) if(target || isDepth(format) || isStencil(format))
{ {
height = ((height + 1) & ~1); height = ((height + 1) & ~1);
...@@ -1752,7 +1765,7 @@ namespace sw ...@@ -1752,7 +1765,7 @@ namespace sw
case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_4x4_KHR:
case FORMAT_RGBA_ASTC_5x4_KHR: case FORMAT_RGBA_ASTC_5x4_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_5x4_KHR:
return pitchB(width, format, target) * ((height + 3) / 4); // Pitch computed per 4 rows return pitchB(width, border, format, target) * ((height + 3) / 4); // Pitch computed per 4 rows
case FORMAT_RGBA_ASTC_5x5_KHR: case FORMAT_RGBA_ASTC_5x5_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_5x5_KHR:
case FORMAT_RGBA_ASTC_6x5_KHR: case FORMAT_RGBA_ASTC_6x5_KHR:
...@@ -1761,39 +1774,39 @@ namespace sw ...@@ -1761,39 +1774,39 @@ namespace sw
case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_8x5_KHR:
case FORMAT_RGBA_ASTC_10x5_KHR: case FORMAT_RGBA_ASTC_10x5_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_10x5_KHR:
return pitchB(width, format, target) * ((height + 4) / 5); // Pitch computed per 5 rows return pitchB(width, border, format, target) * ((height + 4) / 5); // Pitch computed per 5 rows
case FORMAT_RGBA_ASTC_6x6_KHR: case FORMAT_RGBA_ASTC_6x6_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_6x6_KHR:
case FORMAT_RGBA_ASTC_8x6_KHR: case FORMAT_RGBA_ASTC_8x6_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_8x6_KHR:
case FORMAT_RGBA_ASTC_10x6_KHR: case FORMAT_RGBA_ASTC_10x6_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_10x6_KHR:
return pitchB(width, format, target) * ((height + 5) / 6); // Pitch computed per 6 rows return pitchB(width, border, format, target) * ((height + 5) / 6); // Pitch computed per 6 rows
case FORMAT_RGBA_ASTC_8x8_KHR: case FORMAT_RGBA_ASTC_8x8_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_8x8_KHR:
case FORMAT_RGBA_ASTC_10x8_KHR: case FORMAT_RGBA_ASTC_10x8_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_10x8_KHR:
return pitchB(width, format, target) * ((height + 7) / 8); // Pitch computed per 8 rows return pitchB(width, border, format, target) * ((height + 7) / 8); // Pitch computed per 8 rows
case FORMAT_RGBA_ASTC_10x10_KHR: case FORMAT_RGBA_ASTC_10x10_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_10x10_KHR:
case FORMAT_RGBA_ASTC_12x10_KHR: case FORMAT_RGBA_ASTC_12x10_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_12x10_KHR:
return pitchB(width, format, target) * ((height + 9) / 10); // Pitch computed per 10 rows return pitchB(width, border, format, target) * ((height + 9) / 10); // Pitch computed per 10 rows
case FORMAT_RGBA_ASTC_12x12_KHR: case FORMAT_RGBA_ASTC_12x12_KHR:
case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR: case FORMAT_SRGB8_ALPHA8_ASTC_12x12_KHR:
return pitchB(width, format, target) * ((height + 11) / 12); // Pitch computed per 12 rows return pitchB(width, border, format, target) * ((height + 11) / 12); // Pitch computed per 12 rows
case FORMAT_ATI1: case FORMAT_ATI1:
case FORMAT_ATI2: case FORMAT_ATI2:
default: default:
return pitchB(width, format, target) * height; // Pitch computed per row return pitchB(width, border, format, target) * height; // Pitch computed per row
} }
} }
int Surface::sliceP(int width, int height, Format format, bool target) int Surface::sliceP(int width, int height, int border, Format format, bool target)
{ {
int B = bytes(format); int B = bytes(format);
return B > 0 ? sliceB(width, height, format, target) / B : 0; return B > 0 ? sliceB(width, height, border, format, target) / B : 0;
} }
void Surface::update(Buffer &destination, Buffer &source) void Surface::update(Buffer &destination, Buffer &source)
...@@ -1866,8 +1879,8 @@ namespace sw ...@@ -1866,8 +1879,8 @@ namespace sw
void Surface::genericUpdate(Buffer &destination, Buffer &source) void Surface::genericUpdate(Buffer &destination, Buffer &source)
{ {
unsigned char *sourceSlice = (unsigned char*)source.buffer; unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
unsigned char *destinationSlice = (unsigned char*)destination.buffer; unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
int depth = min(destination.depth, source.depth); int depth = min(destination.depth, source.depth);
int height = min(destination.height, source.height); int height = min(destination.height, source.height);
...@@ -1907,12 +1920,15 @@ namespace sw ...@@ -1907,12 +1920,15 @@ namespace sw
sourceSlice += source.sliceB; sourceSlice += source.sliceB;
destinationSlice += destination.sliceB; destinationSlice += destination.sliceB;
} }
source.unlockRect();
destination.unlockRect();
} }
void Surface::decodeR8G8B8(Buffer &destination, const Buffer &source) void Surface::decodeR8G8B8(Buffer &destination, Buffer &source)
{ {
unsigned char *sourceSlice = (unsigned char*)source.buffer; unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
unsigned char *destinationSlice = (unsigned char*)destination.buffer; unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
for(int z = 0; z < destination.depth && z < source.depth; z++) for(int z = 0; z < destination.depth && z < source.depth; z++)
{ {
...@@ -1943,12 +1959,15 @@ namespace sw ...@@ -1943,12 +1959,15 @@ namespace sw
sourceSlice += source.sliceB; sourceSlice += source.sliceB;
destinationSlice += destination.sliceB; destinationSlice += destination.sliceB;
} }
source.unlockRect();
destination.unlockRect();
} }
void Surface::decodeX1R5G5B5(Buffer &destination, const Buffer &source) void Surface::decodeX1R5G5B5(Buffer &destination, Buffer &source)
{ {
unsigned char *sourceSlice = (unsigned char*)source.buffer; unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
unsigned char *destinationSlice = (unsigned char*)destination.buffer; unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
for(int z = 0; z < destination.depth && z < source.depth; z++) for(int z = 0; z < destination.depth && z < source.depth; z++)
{ {
...@@ -1981,12 +2000,15 @@ namespace sw ...@@ -1981,12 +2000,15 @@ namespace sw
sourceSlice += source.sliceB; sourceSlice += source.sliceB;
destinationSlice += destination.sliceB; destinationSlice += destination.sliceB;
} }
source.unlockRect();
destination.unlockRect();
} }
void Surface::decodeA1R5G5B5(Buffer &destination, const Buffer &source) void Surface::decodeA1R5G5B5(Buffer &destination, Buffer &source)
{ {
unsigned char *sourceSlice = (unsigned char*)source.buffer; unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
unsigned char *destinationSlice = (unsigned char*)destination.buffer; unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
for(int z = 0; z < destination.depth && z < source.depth; z++) for(int z = 0; z < destination.depth && z < source.depth; z++)
{ {
...@@ -2020,12 +2042,15 @@ namespace sw ...@@ -2020,12 +2042,15 @@ namespace sw
sourceSlice += source.sliceB; sourceSlice += source.sliceB;
destinationSlice += destination.sliceB; destinationSlice += destination.sliceB;
} }
source.unlockRect();
destination.unlockRect();
} }
void Surface::decodeX4R4G4B4(Buffer &destination, const Buffer &source) void Surface::decodeX4R4G4B4(Buffer &destination, Buffer &source)
{ {
unsigned char *sourceSlice = (unsigned char*)source.buffer; unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
unsigned char *destinationSlice = (unsigned char*)destination.buffer; unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
for(int z = 0; z < destination.depth && z < source.depth; z++) for(int z = 0; z < destination.depth && z < source.depth; z++)
{ {
...@@ -2058,12 +2083,15 @@ namespace sw ...@@ -2058,12 +2083,15 @@ namespace sw
sourceSlice += source.sliceB; sourceSlice += source.sliceB;
destinationSlice += destination.sliceB; destinationSlice += destination.sliceB;
} }
source.unlockRect();
destination.unlockRect();
} }
void Surface::decodeA4R4G4B4(Buffer &destination, const Buffer &source) void Surface::decodeA4R4G4B4(Buffer &destination, Buffer &source)
{ {
unsigned char *sourceSlice = (unsigned char*)source.buffer; unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
unsigned char *destinationSlice = (unsigned char*)destination.buffer; unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
for(int z = 0; z < destination.depth && z < source.depth; z++) for(int z = 0; z < destination.depth && z < source.depth; z++)
{ {
...@@ -2097,12 +2125,15 @@ namespace sw ...@@ -2097,12 +2125,15 @@ namespace sw
sourceSlice += source.sliceB; sourceSlice += source.sliceB;
destinationSlice += destination.sliceB; destinationSlice += destination.sliceB;
} }
source.unlockRect();
destination.unlockRect();
} }
void Surface::decodeP8(Buffer &destination, const Buffer &source) void Surface::decodeP8(Buffer &destination, Buffer &source)
{ {
unsigned char *sourceSlice = (unsigned char*)source.buffer; unsigned char *sourceSlice = (unsigned char*)source.lockRect(0, 0, 0, sw::LOCK_READONLY);
unsigned char *destinationSlice = (unsigned char*)destination.buffer; unsigned char *destinationSlice = (unsigned char*)destination.lockRect(0, 0, 0, sw::LOCK_WRITEONLY);
for(int z = 0; z < destination.depth && z < source.depth; z++) for(int z = 0; z < destination.depth && z < source.depth; z++)
{ {
...@@ -2136,13 +2167,16 @@ namespace sw ...@@ -2136,13 +2167,16 @@ namespace sw
sourceSlice += source.sliceB; sourceSlice += source.sliceB;
destinationSlice += destination.sliceB; destinationSlice += destination.sliceB;
} }
source.unlockRect();
destination.unlockRect();
} }
#if S3TC_SUPPORT #if S3TC_SUPPORT
void Surface::decodeDXT1(Buffer &internal, const Buffer &external) void Surface::decodeDXT1(Buffer &internal, Buffer &external)
{ {
unsigned int *destSlice = (unsigned int*)internal.buffer; unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
const DXT1 *source = (const DXT1*)external.buffer; const DXT1 *source = (const DXT1*)external.lockRect(0, 0, 0, LOCK_READONLY);
for(int z = 0; z < external.depth; z++) for(int z = 0; z < external.depth; z++)
{ {
...@@ -2199,12 +2233,15 @@ namespace sw ...@@ -2199,12 +2233,15 @@ namespace sw
(byte*&)destSlice += internal.sliceB; (byte*&)destSlice += internal.sliceB;
} }
external.unlockRect();
internal.unlockRect();
} }
void Surface::decodeDXT3(Buffer &internal, const Buffer &external) void Surface::decodeDXT3(Buffer &internal, Buffer &external)
{ {
unsigned int *destSlice = (unsigned int*)internal.buffer; unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
const DXT3 *source = (const DXT3*)external.buffer; const DXT3 *source = (const DXT3*)external.lockRect(0, 0, 0, LOCK_READONLY);
for(int z = 0; z < external.depth; z++) for(int z = 0; z < external.depth; z++)
{ {
...@@ -2246,12 +2283,15 @@ namespace sw ...@@ -2246,12 +2283,15 @@ namespace sw
(byte*&)destSlice += internal.sliceB; (byte*&)destSlice += internal.sliceB;
} }
external.unlockRect();
internal.unlockRect();
} }
void Surface::decodeDXT5(Buffer &internal, const Buffer &external) void Surface::decodeDXT5(Buffer &internal, Buffer &external)
{ {
unsigned int *destSlice = (unsigned int*)internal.buffer; unsigned int *destSlice = (unsigned int*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
const DXT5 *source = (const DXT5*)external.buffer; const DXT5 *source = (const DXT5*)external.lockRect(0, 0, 0, LOCK_READONLY);
for(int z = 0; z < external.depth; z++) for(int z = 0; z < external.depth; z++)
{ {
...@@ -2317,13 +2357,16 @@ namespace sw ...@@ -2317,13 +2357,16 @@ namespace sw
(byte*&)destSlice += internal.sliceB; (byte*&)destSlice += internal.sliceB;
} }
external.unlockRect();
internal.unlockRect();
} }
#endif #endif
void Surface::decodeATI1(Buffer &internal, const Buffer &external) void Surface::decodeATI1(Buffer &internal, Buffer &external)
{ {
byte *destSlice = (byte*)internal.buffer; byte *destSlice = (byte*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
const ATI1 *source = (const ATI1*)external.buffer; const ATI1 *source = (const ATI1*)external.lockRect(0, 0, 0, LOCK_READONLY);
for(int z = 0; z < external.depth; z++) for(int z = 0; z < external.depth; z++)
{ {
...@@ -2371,12 +2414,15 @@ namespace sw ...@@ -2371,12 +2414,15 @@ namespace sw
destSlice += internal.sliceB; destSlice += internal.sliceB;
} }
external.unlockRect();
internal.unlockRect();
} }
void Surface::decodeATI2(Buffer &internal, const Buffer &external) void Surface::decodeATI2(Buffer &internal, Buffer &external)
{ {
word *destSlice = (word*)internal.buffer; word *destSlice = (word*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY);
const ATI2 *source = (const ATI2*)external.buffer; const ATI2 *source = (const ATI2*)external.lockRect(0, 0, 0, LOCK_READONLY);
for(int z = 0; z < external.depth; z++) for(int z = 0; z < external.depth; z++)
{ {
...@@ -2451,12 +2497,17 @@ namespace sw ...@@ -2451,12 +2497,17 @@ namespace sw
(byte*&)destSlice += internal.sliceB; (byte*&)destSlice += internal.sliceB;
} }
external.unlockRect();
internal.unlockRect();
} }
void Surface::decodeETC2(Buffer &internal, const Buffer &external, int nbAlphaBits, bool isSRGB) void Surface::decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB)
{ {
ETC_Decoder::Decode((const byte*)external.buffer, (byte*)internal.buffer, external.width, external.height, internal.width, internal.height, internal.pitchB, internal.bytes, ETC_Decoder::Decode((const byte*)external.lockRect(0, 0, 0, LOCK_READONLY), (byte*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY), external.width, external.height, internal.width, internal.height, internal.pitchB, internal.bytes,
(nbAlphaBits == 8) ? ETC_Decoder::ETC_RGBA : ((nbAlphaBits == 1) ? ETC_Decoder::ETC_RGB_PUNCHTHROUGH_ALPHA : ETC_Decoder::ETC_RGB)); (nbAlphaBits == 8) ? ETC_Decoder::ETC_RGBA : ((nbAlphaBits == 1) ? ETC_Decoder::ETC_RGB_PUNCHTHROUGH_ALPHA : ETC_Decoder::ETC_RGB));
external.unlockRect();
internal.unlockRect();
if(isSRGB) if(isSRGB)
{ {
...@@ -2472,34 +2523,37 @@ namespace sw ...@@ -2472,34 +2523,37 @@ namespace sw
} }
// Perform sRGB conversion in place after decoding // Perform sRGB conversion in place after decoding
byte* src = (byte*)internal.buffer; byte *src = (byte*)internal.lockRect(0, 0, 0, LOCK_READWRITE);
for(int y = 0; y < internal.height; y++) for(int y = 0; y < internal.height; y++)
{ {
byte* srcRow = src + y * internal.pitchB; byte *srcRow = src + y * internal.pitchB;
for(int x = 0; x < internal.width; x++) for(int x = 0; x < internal.width; x++)
{ {
byte* srcPix = srcRow + x * internal.bytes; byte *srcPix = srcRow + x * internal.bytes;
for(int i = 0; i < 3; i++) for(int i = 0; i < 3; i++)
{ {
srcPix[i] = sRGBtoLinearTable[srcPix[i]]; srcPix[i] = sRGBtoLinearTable[srcPix[i]];
} }
} }
} }
internal.unlockRect();
} }
} }
void Surface::decodeEAC(Buffer &internal, const Buffer &external, int nbChannels, bool isSigned) void Surface::decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned)
{ {
ASSERT(nbChannels == 1 || nbChannels == 2); ASSERT(nbChannels == 1 || nbChannels == 2);
ETC_Decoder::Decode((const byte*)external.buffer, (byte*)internal.buffer, external.width, external.height, internal.width, internal.height, internal.pitchB, internal.bytes, ETC_Decoder::Decode((const byte*)external.lockRect(0, 0, 0, LOCK_READONLY), (byte*)internal.lockRect(0, 0, 0, LOCK_WRITEONLY), external.width, external.height, internal.width, internal.height, internal.pitchB, internal.bytes,
(nbChannels == 1) ? (isSigned ? ETC_Decoder::ETC_R_SIGNED : ETC_Decoder::ETC_R_UNSIGNED) : (isSigned ? ETC_Decoder::ETC_RG_SIGNED : ETC_Decoder::ETC_RG_UNSIGNED)); (nbChannels == 1) ? (isSigned ? ETC_Decoder::ETC_R_SIGNED : ETC_Decoder::ETC_R_UNSIGNED) : (isSigned ? ETC_Decoder::ETC_RG_SIGNED : ETC_Decoder::ETC_RG_UNSIGNED));
external.unlockRect();
internal.unlockRect();
// FIXME: We convert signed data to float, until signed integer internal formats are supported // FIXME: We convert signed data to float, until signed integer internal formats are supported
// This code can be removed if signed ETC2 images are decoded to internal 8 bit signed R/RG formats // This code can be removed if signed ETC2 images are decoded to internal 8 bit signed R/RG formats
if(isSigned) if(isSigned)
{ {
sbyte* src = (sbyte*)internal.buffer; sbyte *src = (sbyte*)internal.lockRect(0, 0, 0, LOCK_READWRITE);
for(int y = 0; y < internal.height; y++) for(int y = 0; y < internal.height; y++)
{ {
...@@ -2517,15 +2571,20 @@ namespace sw ...@@ -2517,15 +2571,20 @@ namespace sw
} }
} }
} }
internal.unlockRect();
} }
} }
void Surface::decodeASTC(Buffer &internal, const Buffer &external, int xBlockSize, int yBlockSize, int zBlockSize, bool isSRGB) void Surface::decodeASTC(Buffer &internal, Buffer &external, int xBlockSize, int yBlockSize, int zBlockSize, bool isSRGB)
{ {
} }
unsigned int Surface::size(int width, int height, int depth, Format format) unsigned int Surface::size(int width, int height, int depth, int border, Format format)
{ {
width += 2 * border;
height += 2 * border;
// Dimensions rounded up to multiples of 4, used for compressed formats // Dimensions rounded up to multiples of 4, used for compressed formats
int width4 = align(width, 4); int width4 = align(width, 4);
int height4 = align(height, 4); int height4 = align(height, 4);
...@@ -3107,7 +3166,7 @@ namespace sw ...@@ -3107,7 +3166,7 @@ namespace sw
return 1; return 1;
} }
void *Surface::allocateBuffer(int width, int height, int depth, Format format) void *Surface::allocateBuffer(int width, int height, int depth, int border, Format format)
{ {
// Render targets require 2x2 quads // Render targets require 2x2 quads
int width2 = (width + 1) & ~1; int width2 = (width + 1) & ~1;
...@@ -3116,7 +3175,7 @@ namespace sw ...@@ -3116,7 +3175,7 @@ namespace sw
// FIXME: Unpacking byte4 to short4 in the sampler currently involves reading 8 bytes, // FIXME: Unpacking byte4 to short4 in the sampler currently involves reading 8 bytes,
// and stencil operations also read 8 bytes per four 8-bit stencil values, // and stencil operations also read 8 bytes per four 8-bit stencil values,
// so we have to allocate 4 extra bytes to avoid buffer overruns. // so we have to allocate 4 extra bytes to avoid buffer overruns.
return allocate(size(width2, height2, depth, format) + 4); return allocate(size(width2, height2, depth, border, format) + 4);
} }
void Surface::memfill4(void *buffer, int pattern, int bytes) void Surface::memfill4(void *buffer, int pattern, int bytes)
...@@ -3537,7 +3596,8 @@ namespace sw ...@@ -3537,7 +3596,8 @@ namespace sw
external.height == internal.height && external.height == internal.height &&
external.depth == internal.depth && external.depth == internal.depth &&
external.pitchB == internal.pitchB && external.pitchB == internal.pitchB &&
external.sliceB == internal.sliceB; external.sliceB == internal.sliceB &&
external.border == internal.border;
} }
Format Surface::selectInternalFormat(Format format) const Format Surface::selectInternalFormat(Format format) const
......
...@@ -244,6 +244,7 @@ namespace sw ...@@ -244,6 +244,7 @@ namespace sw
int pitchP; int pitchP;
int sliceB; int sliceB;
int sliceP; int sliceP;
int border;
Format format; Format format;
AtomicInt lock; AtomicInt lock;
...@@ -252,11 +253,11 @@ namespace sw ...@@ -252,11 +253,11 @@ namespace sw
protected: protected:
Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice); Surface(int width, int height, int depth, Format format, void *pixels, int pitch, int slice);
Surface(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchP = 0); Surface(Resource *texture, int width, int height, int depth, int border, Format format, bool lockable, bool renderTarget, int pitchP = 0);
public: public:
static Surface *create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice); static Surface *create(int width, int height, int depth, Format format, void *pixels, int pitch, int slice);
static Surface *create(Resource *texture, int width, int height, int depth, Format format, bool lockable, bool renderTarget, int pitchP = 0); static Surface *create(Resource *texture, int width, int height, int depth, int border, Format format, bool lockable, bool renderTarget, int pitchP = 0);
virtual ~Surface() = 0; virtual ~Surface() = 0;
...@@ -265,6 +266,7 @@ namespace sw ...@@ -265,6 +266,7 @@ namespace sw
inline int getWidth() const; inline int getWidth() const;
inline int getHeight() const; inline int getHeight() const;
inline int getDepth() const; inline int getDepth() const;
inline int getBorder() const;
inline Format getFormat(bool internal = false) const; inline Format getFormat(bool internal = false) const;
inline int getPitchB(bool internal = false) const; inline int getPitchB(bool internal = false) const;
inline int getPitchP(bool internal = false) const; inline int getPitchP(bool internal = false) const;
...@@ -326,11 +328,11 @@ namespace sw ...@@ -326,11 +328,11 @@ namespace sw
Resource *getResource(); Resource *getResource();
static int bytes(Format format); static int bytes(Format format);
static int pitchB(int width, Format format, bool target); static int pitchB(int width, int border, Format format, bool target);
static int pitchP(int width, Format format, bool target); static int pitchP(int width, int border, Format format, bool target);
static int sliceB(int width, int height, Format format, bool target); static int sliceB(int width, int height, int border, Format format, bool target);
static int sliceP(int width, int height, Format format, bool target); static int sliceP(int width, int height, int border, Format format, bool target);
static unsigned int size(int width, int height, int depth, Format format); // FIXME: slice * depth static unsigned int size(int width, int height, int depth, int border, Format format); // FIXME: slice * depth
static bool isStencil(Format format); static bool isStencil(Format format);
static bool isDepth(Format format); static bool isDepth(Format format);
...@@ -433,27 +435,27 @@ namespace sw ...@@ -433,27 +435,27 @@ namespace sw
}; };
}; };
static void decodeR8G8B8(Buffer &destination, const Buffer &source); static void decodeR8G8B8(Buffer &destination, Buffer &source);
static void decodeX1R5G5B5(Buffer &destination, const Buffer &source); static void decodeX1R5G5B5(Buffer &destination, Buffer &source);
static void decodeA1R5G5B5(Buffer &destination, const Buffer &source); static void decodeA1R5G5B5(Buffer &destination, Buffer &source);
static void decodeX4R4G4B4(Buffer &destination, const Buffer &source); static void decodeX4R4G4B4(Buffer &destination, Buffer &source);
static void decodeA4R4G4B4(Buffer &destination, const Buffer &source); static void decodeA4R4G4B4(Buffer &destination, Buffer &source);
static void decodeP8(Buffer &destination, const Buffer &source); static void decodeP8(Buffer &destination, Buffer &source);
#if S3TC_SUPPORT #if S3TC_SUPPORT
static void decodeDXT1(Buffer &internal, const Buffer &external); static void decodeDXT1(Buffer &internal, Buffer &external);
static void decodeDXT3(Buffer &internal, const Buffer &external); static void decodeDXT3(Buffer &internal, Buffer &external);
static void decodeDXT5(Buffer &internal, const Buffer &external); static void decodeDXT5(Buffer &internal, Buffer &external);
#endif #endif
static void decodeATI1(Buffer &internal, const Buffer &external); static void decodeATI1(Buffer &internal, Buffer &external);
static void decodeATI2(Buffer &internal, const Buffer &external); static void decodeATI2(Buffer &internal, Buffer &external);
static void decodeEAC(Buffer &internal, const Buffer &external, int nbChannels, bool isSigned); static void decodeEAC(Buffer &internal, Buffer &external, int nbChannels, bool isSigned);
static void decodeETC2(Buffer &internal, const Buffer &external, int nbAlphaBits, bool isSRGB); static void decodeETC2(Buffer &internal, Buffer &external, int nbAlphaBits, bool isSRGB);
static void decodeASTC(Buffer &internal, const Buffer &external, int xSize, int ySize, int zSize, bool isSRGB); static void decodeASTC(Buffer &internal, Buffer &external, int xSize, int ySize, int zSize, bool isSRGB);
static void update(Buffer &destination, Buffer &source); static void update(Buffer &destination, Buffer &source);
static void genericUpdate(Buffer &destination, Buffer &source); static void genericUpdate(Buffer &destination, Buffer &source);
static void *allocateBuffer(int width, int height, int depth, Format format); static void *allocateBuffer(int width, int height, int depth, int border, Format format);
static void memfill4(void *buffer, int pattern, int bytes); static void memfill4(void *buffer, int pattern, int bytes);
bool identicalFormats() const; bool identicalFormats() const;
...@@ -509,6 +511,11 @@ namespace sw ...@@ -509,6 +511,11 @@ namespace sw
return external.depth; return external.depth;
} }
int Surface::getBorder() const
{
return internal.border;
}
Format Surface::getFormat(bool internal) const Format Surface::getFormat(bool internal) const
{ {
return internal ? getInternalFormat() : getExternalFormat(); return internal ? getInternalFormat() : getExternalFormat();
......
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