Bug 1305832 - Move texture clearing code into WebGLTexture.cpp. - r=ethlin

MozReview-Commit-ID: 30UcfPZLYNz
This commit is contained in:
Jeff Gilbert 2016-12-09 10:22:22 -10:00
parent ab01d38382
commit 7ca1cb79d0
3 changed files with 154 additions and 160 deletions

View File

@ -2221,160 +2221,6 @@ Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
*out_intSize = std::max<int32_t>(0, intEndInSrc - *out_intStartInSrc);
}
static void
ZeroANGLEDepthTexture(WebGLContext* webgl, GLuint tex,
const webgl::FormatUsageInfo* usage, uint32_t width,
uint32_t height)
{
const auto& format = usage->format;
GLenum attachPoint = 0;
GLbitfield clearBits = 0;
if (format->d) {
attachPoint = LOCAL_GL_DEPTH_ATTACHMENT;
clearBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
}
if (format->s) {
attachPoint = (format->d ? LOCAL_GL_DEPTH_STENCIL_ATTACHMENT
: LOCAL_GL_STENCIL_ATTACHMENT);
clearBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
}
MOZ_RELEASE_ASSERT(attachPoint && clearBits, "GFX: No bits cleared.");
////
const auto& gl = webgl->gl;
MOZ_ASSERT(gl->IsCurrent());
ScopedFramebuffer scopedFB(gl);
ScopedBindFramebuffer scopedBindFB(gl, scopedFB.FB());
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachPoint, LOCAL_GL_TEXTURE_2D,
tex, 0);
const auto& status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
MOZ_RELEASE_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE);
////
const bool fakeNoAlpha = false;
webgl->ForceClearFramebufferWithDefaultValues(clearBits, fakeNoAlpha);
}
bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, GLuint tex,
TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t width, uint32_t height,
uint32_t depth)
{
// This has two usecases:
// 1. Lazy zeroing of uninitialized textures:
// a. Before draw, when FakeBlack isn't viable. (TexStorage + Draw*)
// b. Before partial upload. (TexStorage + TexSubImage)
// 2. Zero subrects from out-of-bounds blits. (CopyTex(Sub)Image)
// We have no sympathy for any of these cases.
// "Doctor, it hurts when I do this!" "Well don't do that!"
webgl->GenerateWarning("%s: This operation requires zeroing texture data. This is"
" slow.",
funcName);
gl::GLContext* gl = webgl->GL();
gl->MakeCurrent();
GLenum scopeBindTarget;
switch (target.get()) {
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
scopeBindTarget = LOCAL_GL_TEXTURE_CUBE_MAP;
break;
default:
scopeBindTarget = target.get();
break;
}
ScopedBindTexture scopeBindTexture(gl, tex, scopeBindTarget);
auto compression = usage->format->compression;
if (compression) {
auto sizedFormat = usage->format->sizedFormat;
MOZ_RELEASE_ASSERT(sizedFormat, "GFX: texture sized format not set");
const auto fnSizeInBlocks = [](CheckedUint32 pixels, uint8_t pixelsPerBlock) {
return RoundUpToMultipleOf(pixels, pixelsPerBlock) / pixelsPerBlock;
};
const auto widthBlocks = fnSizeInBlocks(width, compression->blockWidth);
const auto heightBlocks = fnSizeInBlocks(height, compression->blockHeight);
CheckedUint32 checkedByteCount = compression->bytesPerBlock;
checkedByteCount *= widthBlocks;
checkedByteCount *= heightBlocks;
checkedByteCount *= depth;
if (!checkedByteCount.isValid())
return false;
const size_t byteCount = checkedByteCount.value();
UniqueBuffer zeros = calloc(1, byteCount);
if (!zeros)
return false;
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it
// well.
const auto error = DoCompressedTexSubImage(gl, target.get(), level, 0, 0, 0,
width, height, depth, sizedFormat,
byteCount, zeros.get());
return !error;
}
const auto driverUnpackInfo = usage->idealUnpack;
MOZ_RELEASE_ASSERT(driverUnpackInfo, "GFX: ideal unpack info not set.");
if (webgl->IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
gl->IsANGLE() &&
usage->format->d)
{
// ANGLE_depth_texture does not allow uploads, so we have to clear.
// (Restriction because of D3D9)
MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D);
MOZ_ASSERT(level == 0);
ZeroANGLEDepthTexture(webgl, tex, usage, width, height);
return true;
}
const webgl::PackingInfo packing = driverUnpackInfo->ToPacking();
const auto bytesPerPixel = webgl::BytesPerPixel(packing);
CheckedUint32 checkedByteCount = bytesPerPixel;
checkedByteCount *= width;
checkedByteCount *= height;
checkedByteCount *= depth;
if (!checkedByteCount.isValid())
return false;
const size_t byteCount = checkedByteCount.value();
UniqueBuffer zeros = calloc(1, byteCount);
if (!zeros)
return false;
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it well.
const auto error = DoTexSubImage(gl, target, level, 0, 0, 0, width, height, depth,
packing, zeros.get());
return !error;
}
////////////////////////////////////////////////////////////////////////////////
CheckedUint32

View File

@ -2132,12 +2132,6 @@ Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
uint32_t* const out_intStartInSrc, uint32_t* const out_intStartInDst,
uint32_t* const out_intSize);
bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, GLuint tex,
TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t width, uint32_t height,
uint32_t depth);
////
void

View File

@ -583,6 +583,160 @@ WebGLTexture::EnsureImageDataInitialized(const char* funcName, TexImageTarget ta
return InitializeImageData(funcName, target, level);
}
static void
ZeroANGLEDepthTexture(WebGLContext* webgl, GLuint tex,
const webgl::FormatUsageInfo* usage, uint32_t width,
uint32_t height)
{
const auto& format = usage->format;
GLenum attachPoint = 0;
GLbitfield clearBits = 0;
if (format->d) {
attachPoint = LOCAL_GL_DEPTH_ATTACHMENT;
clearBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
}
if (format->s) {
attachPoint = (format->d ? LOCAL_GL_DEPTH_STENCIL_ATTACHMENT
: LOCAL_GL_STENCIL_ATTACHMENT);
clearBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
}
MOZ_RELEASE_ASSERT(attachPoint && clearBits, "GFX: No bits cleared.");
////
const auto& gl = webgl->gl;
MOZ_ASSERT(gl->IsCurrent());
gl::ScopedFramebuffer scopedFB(gl);
const gl::ScopedBindFramebuffer scopedBindFB(gl, scopedFB.FB());
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachPoint, LOCAL_GL_TEXTURE_2D,
tex, 0);
const auto& status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
MOZ_RELEASE_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE);
////
const bool fakeNoAlpha = false;
webgl->ForceClearFramebufferWithDefaultValues(clearBits, fakeNoAlpha);
}
static bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, GLuint tex,
TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t width, uint32_t height,
uint32_t depth)
{
// This has two usecases:
// 1. Lazy zeroing of uninitialized textures:
// a. Before draw, when FakeBlack isn't viable. (TexStorage + Draw*)
// b. Before partial upload. (TexStorage + TexSubImage)
// 2. Zero subrects from out-of-bounds blits. (CopyTex(Sub)Image)
// We have no sympathy for any of these cases.
// "Doctor, it hurts when I do this!" "Well don't do that!"
webgl->GenerateWarning("%s: This operation requires zeroing texture data. This is"
" slow.",
funcName);
gl::GLContext* gl = webgl->GL();
gl->MakeCurrent();
GLenum scopeBindTarget;
switch (target.get()) {
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
scopeBindTarget = LOCAL_GL_TEXTURE_CUBE_MAP;
break;
default:
scopeBindTarget = target.get();
break;
}
const gl::ScopedBindTexture scopeBindTexture(gl, tex, scopeBindTarget);
auto compression = usage->format->compression;
if (compression) {
auto sizedFormat = usage->format->sizedFormat;
MOZ_RELEASE_ASSERT(sizedFormat, "GFX: texture sized format not set");
const auto fnSizeInBlocks = [](CheckedUint32 pixels, uint8_t pixelsPerBlock) {
return RoundUpToMultipleOf(pixels, pixelsPerBlock) / pixelsPerBlock;
};
const auto widthBlocks = fnSizeInBlocks(width, compression->blockWidth);
const auto heightBlocks = fnSizeInBlocks(height, compression->blockHeight);
CheckedUint32 checkedByteCount = compression->bytesPerBlock;
checkedByteCount *= widthBlocks;
checkedByteCount *= heightBlocks;
checkedByteCount *= depth;
if (!checkedByteCount.isValid())
return false;
const size_t byteCount = checkedByteCount.value();
UniqueBuffer zeros = calloc(1, byteCount);
if (!zeros)
return false;
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it
// well.
const auto error = DoCompressedTexSubImage(gl, target.get(), level, 0, 0, 0,
width, height, depth, sizedFormat,
byteCount, zeros.get());
return !error;
}
const auto driverUnpackInfo = usage->idealUnpack;
MOZ_RELEASE_ASSERT(driverUnpackInfo, "GFX: ideal unpack info not set.");
if (webgl->IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
gl->IsANGLE() &&
usage->format->d)
{
// ANGLE_depth_texture does not allow uploads, so we have to clear.
// (Restriction because of D3D9)
MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D);
MOZ_ASSERT(level == 0);
ZeroANGLEDepthTexture(webgl, tex, usage, width, height);
return true;
}
const webgl::PackingInfo packing = driverUnpackInfo->ToPacking();
const auto bytesPerPixel = webgl::BytesPerPixel(packing);
CheckedUint32 checkedByteCount = bytesPerPixel;
checkedByteCount *= width;
checkedByteCount *= height;
checkedByteCount *= depth;
if (!checkedByteCount.isValid())
return false;
const size_t byteCount = checkedByteCount.value();
UniqueBuffer zeros = calloc(1, byteCount);
if (!zeros)
return false;
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it well.
const auto error = DoTexSubImage(gl, target, level, 0, 0, 0, width, height, depth,
packing, zeros.get());
return !error;
}
bool
WebGLTexture::InitializeImageData(const char* funcName, TexImageTarget target,
uint32_t level)