mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 922810 - Part 8: Defer/avoid initialization of texture images - r=jgilbert
This commit is contained in:
parent
7ae9b37393
commit
ad878d159b
@ -680,6 +680,10 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||
return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
|
||||
|
||||
if (imageInfo.HasUninitializedImageData()) {
|
||||
tex->DoDeferredImageInitialization(target, level);
|
||||
}
|
||||
|
||||
return CopyTexSubImage2D_base(target, level, format, xoffset, yoffset, x, y, width, height, true);
|
||||
}
|
||||
|
||||
@ -1035,14 +1039,15 @@ WebGLContext::BindFakeBlackTexturesHelper(
|
||||
continue;
|
||||
}
|
||||
|
||||
bool opaque = s == WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
|
||||
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().Format());
|
||||
ScopedDeletePtr<FakeBlackTexture>&
|
||||
blackTexturePtr = opaque
|
||||
? opaqueTextureScopedPtr
|
||||
: transparentTextureScopedPtr;
|
||||
blackTexturePtr = alpha
|
||||
? transparentTextureScopedPtr
|
||||
: opaqueTextureScopedPtr;
|
||||
|
||||
if (!blackTexturePtr) {
|
||||
GLenum format = opaque ? LOCAL_GL_RGB : LOCAL_GL_RGBA;
|
||||
GLenum format = alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
|
||||
blackTexturePtr
|
||||
= new FakeBlackTexture(gl, target, format);
|
||||
}
|
||||
@ -3470,6 +3475,10 @@ WebGLContext::CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
|
||||
}
|
||||
}
|
||||
|
||||
if (imageInfo.HasUninitializedImageData()) {
|
||||
tex->DoDeferredImageInitialization(target, level);
|
||||
}
|
||||
|
||||
gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.Data());
|
||||
|
||||
return;
|
||||
@ -3810,28 +3819,9 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
||||
}
|
||||
imageInfoStatusIfSuccess = WebGLImageDataStatus::InitializedImageData;
|
||||
} else {
|
||||
if (isDepthTexture) {
|
||||
// When ANGLE_depth_texture is all we have, we cannot use texImage2D
|
||||
// to upload anything to a depth texture. Fortunately, the WEBGL_depth_texture
|
||||
// spec guarantees that there is no other image on this texture, and that
|
||||
// texSubImage2D cannot be used on it. So we just do not initialize this
|
||||
// image, and instead mark it as uninitialized so that a fake black texture
|
||||
// will be sampled from instead.
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, nullptr);
|
||||
imageInfoStatusIfSuccess = WebGLImageDataStatus::UninitializedImageData;
|
||||
} else {
|
||||
// We need some zero pages, because GL doesn't guarantee the
|
||||
// contents of a texture allocated with nullptr data.
|
||||
// Hopefully calloc will just mmap zero pages here.
|
||||
void *tempZeroData = calloc(1, bytesNeeded);
|
||||
if (!tempZeroData)
|
||||
return ErrorOutOfMemory("texImage2D: could not allocate %d bytes (for zero fill)", bytesNeeded);
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, tempZeroData);
|
||||
free(tempZeroData);
|
||||
imageInfoStatusIfSuccess = WebGLImageDataStatus::InitializedImageData;
|
||||
}
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, nullptr);
|
||||
imageInfoStatusIfSuccess = WebGLImageDataStatus::UninitializedImageData;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
@ -3967,6 +3957,10 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
|
||||
if (imageInfo.Format() != format || imageInfo.Type() != type)
|
||||
return ErrorInvalidOperation("texSubImage2D: format or type doesn't match the existing texture");
|
||||
|
||||
if (imageInfo.HasUninitializedImageData()) {
|
||||
tex->DoDeferredImageInitialization(target, level);
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLTexture.h"
|
||||
#include "GLContext.h"
|
||||
#include "WebGLTexelConversions.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include <algorithm>
|
||||
|
||||
@ -358,9 +359,44 @@ WebGLTexture::ResolvedFakeBlackStatus() {
|
||||
hasUninitializedImageData |= (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUninitializedImageData) {
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::UninitializedImageData;
|
||||
return mFakeBlackStatus;
|
||||
bool hasAnyInitializedImageData = false;
|
||||
for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
if (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::InitializedImageData) {
|
||||
hasAnyInitializedImageData = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasAnyInitializedImageData) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAnyInitializedImageData) {
|
||||
// The texture contains some initialized image data, and some uninitialized image data.
|
||||
// In this case, we have no choice but to initialize all image data now. Fortunately,
|
||||
// in this case we know that we can't be dealing with a depth texture per WEBGL_depth_texture
|
||||
// and ANGLE_depth_texture (which allow only one image per texture) so we can assume that
|
||||
// glTexImage2D is able to upload data to images.
|
||||
for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
GLenum imageTarget = mTarget == LOCAL_GL_TEXTURE_2D
|
||||
? LOCAL_GL_TEXTURE_2D
|
||||
: LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
||||
const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
|
||||
if (imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData) {
|
||||
DoDeferredImageInitialization(imageTarget, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
} else {
|
||||
// The texture only contains uninitialized image data. In this case,
|
||||
// we can use a black texture for it.
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::UninitializedImageData;
|
||||
}
|
||||
}
|
||||
|
||||
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
|
||||
@ -373,6 +409,41 @@ WebGLTexture::ResolvedFakeBlackStatus() {
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::DoDeferredImageInitialization(GLenum imageTarget, GLint level)
|
||||
{
|
||||
const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
|
||||
MOZ_ASSERT(imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
gl::ScopedBindTexture autoBindTex(mContext->gl, GLName(), mTarget);
|
||||
|
||||
WebGLTexelFormat texelformat = GetWebGLTexelFormat(imageInfo.mFormat, imageInfo.mType);
|
||||
uint32_t texelsize = WebGLTexelConversions::TexelBytesForFormat(texelformat);
|
||||
CheckedUint32 checked_byteLength
|
||||
= WebGLContext::GetImageSize(
|
||||
imageInfo.mHeight,
|
||||
imageInfo.mWidth,
|
||||
texelsize,
|
||||
mContext->mPixelStoreUnpackAlignment);
|
||||
MOZ_ASSERT(checked_byteLength.isValid()); // should have been checked earlier
|
||||
void *zeros = calloc(1, checked_byteLength.value());
|
||||
GLenum error
|
||||
= mContext->CheckedTexImage2D(imageTarget, level, imageInfo.mFormat,
|
||||
imageInfo.mWidth, imageInfo.mHeight,
|
||||
0, imageInfo.mFormat, imageInfo.mType,
|
||||
zeros);
|
||||
|
||||
free(zeros);
|
||||
SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
|
||||
|
||||
if (error) {
|
||||
// Should only be OUT_OF_MEMORY. Anyway, there's no good way to recover from this here.
|
||||
MOZ_CRASH(); // errors on texture upload have been related to video memory exposure in the past.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTexture, AddRef)
|
||||
|
@ -196,6 +196,8 @@ public:
|
||||
imageInfo.mImageDataStatus = newStatus;
|
||||
}
|
||||
|
||||
void DoDeferredImageInitialization(GLenum imageTarget, GLint level);
|
||||
|
||||
protected:
|
||||
|
||||
GLenum mTarget;
|
||||
|
Loading…
Reference in New Issue
Block a user