зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1006908 - WebGL differentiate texture image targets vs texture binding locations better. r=jgilbert
This commit is contained in:
Родитель
434d96be0b
Коммит
b7556664b4
|
@ -271,7 +271,9 @@ WebGLContext::WebGLContext()
|
|||
mGLMaxVertexAttribs = 0;
|
||||
mGLMaxTextureUnits = 0;
|
||||
mGLMaxTextureSize = 0;
|
||||
mGLMaxTextureSizeLog2 = 0;
|
||||
mGLMaxCubeMapTextureSize = 0;
|
||||
mGLMaxCubeMapTextureSizeLog2 = 0;
|
||||
mGLMaxRenderbufferSize = 0;
|
||||
mGLMaxTextureImageUnits = 0;
|
||||
mGLMaxVertexTextureImageUnits = 0;
|
||||
|
@ -1738,7 +1740,7 @@ WebGLContext::GetSurfaceSnapshot(bool* aPremultAlpha)
|
|||
return dt->Snapshot();
|
||||
}
|
||||
|
||||
bool WebGLContext::TexImageFromVideoElement(GLenum target, GLint level,
|
||||
bool WebGLContext::TexImageFromVideoElement(GLenum texImageTarget, GLint level,
|
||||
GLenum internalformat, GLenum format, GLenum type,
|
||||
mozilla::dom::Element& elt)
|
||||
{
|
||||
|
@ -1778,19 +1780,19 @@ bool WebGLContext::TexImageFromVideoElement(GLenum target, GLint level,
|
|||
|
||||
gl->MakeCurrent();
|
||||
nsRefPtr<mozilla::layers::Image> srcImage = container->LockCurrentImage();
|
||||
WebGLTexture* tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
|
||||
|
||||
const WebGLTexture::ImageInfo& info = tex->ImageInfoAt(target, 0);
|
||||
const WebGLTexture::ImageInfo& info = tex->ImageInfoAt(texImageTarget, 0);
|
||||
bool dimensionsMatch = info.Width() == srcImage->GetSize().width &&
|
||||
info.Height() == srcImage->GetSize().height;
|
||||
if (!dimensionsMatch) {
|
||||
// we need to allocation
|
||||
gl->fTexImage2D(target, level, internalformat, srcImage->GetSize().width, srcImage->GetSize().height, 0, format, type, nullptr);
|
||||
gl->fTexImage2D(texImageTarget, level, internalformat, srcImage->GetSize().width, srcImage->GetSize().height, 0, format, type, nullptr);
|
||||
}
|
||||
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(), srcImage->GetSize(), tex->GLName(), target, mPixelStoreFlipY);
|
||||
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(), srcImage->GetSize(), tex->GLName(), texImageTarget, mPixelStoreFlipY);
|
||||
if (ok) {
|
||||
tex->SetImageInfo(target, level, srcImage->GetSize().width, srcImage->GetSize().height, format, type, WebGLImageDataStatus::InitializedImageData);
|
||||
tex->Bind(target);
|
||||
tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width, srcImage->GetSize().height, format, type, WebGLImageDataStatus::InitializedImageData);
|
||||
tex->Bind(TexImageTargetToTexTarget(texImageTarget));
|
||||
}
|
||||
srcImage = nullptr;
|
||||
container->UnlockCurrentImage();
|
||||
|
|
|
@ -122,18 +122,8 @@ struct WebGLContextOptions {
|
|||
bool preserveDrawingBuffer;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool
|
||||
IsTextureBinding(GLenum binding)
|
||||
{
|
||||
switch (binding) {
|
||||
case LOCAL_GL_TEXTURE_BINDING_2D:
|
||||
case LOCAL_GL_TEXTURE_BINDING_CUBE_MAP:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
// From WebGLContextUtils
|
||||
GLenum TexImageTargetToTexTarget(GLenum texImageTarget);
|
||||
|
||||
class WebGLContext :
|
||||
public nsIDOMWebGLRenderingContext,
|
||||
|
@ -232,10 +222,19 @@ public:
|
|||
|
||||
void DummyFramebufferOperation(const char *info);
|
||||
|
||||
WebGLTexture* activeBoundTextureForTarget(GLenum target) const {
|
||||
MOZ_ASSERT(!IsTextureBinding(target));
|
||||
return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
|
||||
: mBoundCubeMapTextures[mActiveTexture];
|
||||
WebGLTexture* activeBoundTextureForTarget(GLenum texTarget) const {
|
||||
MOZ_ASSERT(texTarget == LOCAL_GL_TEXTURE_2D || texTarget == LOCAL_GL_TEXTURE_CUBE_MAP);
|
||||
return texTarget == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
|
||||
: mBoundCubeMapTextures[mActiveTexture];
|
||||
}
|
||||
|
||||
/* Use this function when you have the texture image target, for example:
|
||||
* GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP_[POSITIVE|NEGATIVE]_[X|Y|Z], and
|
||||
* not the actual texture binding target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP.
|
||||
*/
|
||||
WebGLTexture* activeBoundTextureForTexImageTarget(GLenum texImgTarget) const {
|
||||
const GLenum texTarget = TexImageTargetToTexTarget(texImgTarget);
|
||||
return activeBoundTextureForTarget(texTarget);
|
||||
}
|
||||
|
||||
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
@ -464,25 +463,39 @@ public:
|
|||
dom::ImageData* pixels, ErrorResult& rv);
|
||||
// Allow whatever element types the bindings are willing to pass
|
||||
// us in TexImage2D
|
||||
bool TexImageFromVideoElement(GLenum target, GLint level,
|
||||
bool TexImageFromVideoElement(GLenum texImageTarget, GLint level,
|
||||
GLenum internalformat, GLenum format, GLenum type,
|
||||
mozilla::dom::Element& image);
|
||||
|
||||
template<class ElementType>
|
||||
void TexImage2D(GLenum target, GLint level,
|
||||
void TexImage2D(GLenum texImageTarget, GLint level,
|
||||
GLenum internalformat, GLenum format, GLenum type,
|
||||
ElementType& elt, ErrorResult& rv)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
const GLenum target = TexImageTargetToTexTarget(texImageTarget);
|
||||
if (target == LOCAL_GL_NONE)
|
||||
return ErrorInvalidEnumInfo("texImage2D: target", target);
|
||||
|
||||
if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
|
||||
return;
|
||||
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("texImage2D: level is negative");
|
||||
|
||||
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
|
||||
if (level > maxLevel)
|
||||
return ErrorInvalidValue("texImage2D: level %d is too large, max is %d", level, maxLevel);
|
||||
|
||||
WebGLTexture* tex = activeBoundTextureForTarget(target);
|
||||
|
||||
if (!tex)
|
||||
return ErrorInvalidOperation("no texture is bound to this target");
|
||||
|
||||
// Trying to handle the video by GPU directly first
|
||||
if (TexImageFromVideoElement(target, level, internalformat, format, type, elt)) {
|
||||
if (TexImageFromVideoElement(texImageTarget, level, internalformat, format, type, elt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -496,7 +509,7 @@ public:
|
|||
|
||||
gfx::IntSize size = data->GetSize();
|
||||
uint32_t byteLength = data->Stride() * size.height;
|
||||
return TexImage2D_base(target, level, internalformat,
|
||||
return TexImage2D_base(texImageTarget, level, internalformat,
|
||||
size.width, size.height, data->Stride(),
|
||||
0, format, type, data->GetData(), byteLength,
|
||||
-1, srcFormat, mPixelStorePremultiplyAlpha);
|
||||
|
@ -971,7 +984,9 @@ protected:
|
|||
int32_t mGLMaxVertexAttribs;
|
||||
int32_t mGLMaxTextureUnits;
|
||||
int32_t mGLMaxTextureSize;
|
||||
int32_t mGLMaxTextureSizeLog2;
|
||||
int32_t mGLMaxCubeMapTextureSize;
|
||||
int32_t mGLMaxCubeMapTextureSizeLog2;
|
||||
int32_t mGLMaxRenderbufferSize;
|
||||
int32_t mGLMaxTextureImageUnits;
|
||||
int32_t mGLMaxVertexTextureImageUnits;
|
||||
|
@ -1177,6 +1192,12 @@ protected:
|
|||
return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
|
||||
}
|
||||
|
||||
int32_t MaxTextureLevelForTexImageTarget(GLenum texImageTarget) const {
|
||||
const GLenum target = TexImageTargetToTexTarget(texImageTarget);
|
||||
MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D || target == LOCAL_GL_TEXTURE_CUBE_MAP);
|
||||
return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSizeLog2 : mGLMaxCubeMapTextureSizeLog2;
|
||||
}
|
||||
|
||||
/** like glBufferData but if the call may change the buffer size, checks any GL error generated
|
||||
* by this glBufferData call and returns it */
|
||||
GLenum CheckedBufferData(GLenum target,
|
||||
|
|
|
@ -223,18 +223,26 @@ WebGLContext::BindTexture(GLenum target, WebGLTexture *newTex)
|
|||
if (!ValidateObjectAllowDeletedOrNull("bindTexture", newTex))
|
||||
return;
|
||||
|
||||
// silently ignore a deleted texture
|
||||
if (newTex && newTex->IsDeleted())
|
||||
return;
|
||||
if (newTex) {
|
||||
// silently ignore a deleted texture
|
||||
if (newTex->IsDeleted())
|
||||
return;
|
||||
|
||||
if (newTex->Target() != LOCAL_GL_NONE && newTex->Target() != target)
|
||||
return ErrorInvalidOperation("bindTexture: this texture has already been bound to a different target");
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
|
||||
|
||||
if (target == LOCAL_GL_TEXTURE_2D) {
|
||||
currentTexPtr = &mBound2DTextures[mActiveTexture];
|
||||
} else if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
|
||||
currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bindTexture: target", target);
|
||||
switch (target) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
currentTexPtr = &mBound2DTextures[mActiveTexture];
|
||||
break;
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP:
|
||||
currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("bindTexture: target", target);
|
||||
}
|
||||
|
||||
WebGLTextureFakeBlackStatus currentTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
|
@ -378,7 +386,7 @@ WebGLContext::CopyTexSubImage2D_base(GLenum target,
|
|||
|
||||
MakeContextCurrent();
|
||||
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture *tex = activeBoundTextureForTexImageTarget(target);
|
||||
|
||||
if (!tex)
|
||||
return ErrorInvalidOperation("%s: no texture is bound to this target");
|
||||
|
@ -487,7 +495,7 @@ WebGLContext::CopyTexImage2D(GLenum target,
|
|||
|
||||
// check if the memory size of this texture may change with this call
|
||||
bool sizeMayChange = true;
|
||||
WebGLTexture* tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture* tex = activeBoundTextureForTexImageTarget(target);
|
||||
if (tex->HasImageInfoAt(target, level)) {
|
||||
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(target, level);
|
||||
|
||||
|
@ -553,7 +561,7 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
|
|||
if (xoffset < 0 || yoffset < 0)
|
||||
return ErrorInvalidValue("copyTexSubImage2D: xoffset and yoffset may not be negative");
|
||||
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture *tex = activeBoundTextureForTexImageTarget(target);
|
||||
if (!tex)
|
||||
return ErrorInvalidOperation("copyTexSubImage2D: no texture bound to this target");
|
||||
|
||||
|
@ -3299,7 +3307,7 @@ WebGLContext::CompressedTexImage2D(GLenum target, GLint level, GLenum internalfo
|
|||
|
||||
MakeContextCurrent();
|
||||
gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
|
||||
WebGLTexture* tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture* tex = activeBoundTextureForTexImageTarget(target);
|
||||
MOZ_ASSERT(tex);
|
||||
tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE,
|
||||
WebGLImageDataStatus::InitializedImageData);
|
||||
|
@ -3325,7 +3333,7 @@ WebGLContext::CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
|
|||
return;
|
||||
}
|
||||
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture *tex = activeBoundTextureForTexImageTarget(target);
|
||||
MOZ_ASSERT(tex);
|
||||
WebGLTexture::ImageInfo& levelInfo = tex->ImageInfoAt(target, level);
|
||||
|
||||
|
@ -3546,7 +3554,7 @@ GLenum WebGLContext::CheckedTexImage2D(GLenum target,
|
|||
const GLvoid *data)
|
||||
{
|
||||
MOZ_ASSERT(internalFormat == format);
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture *tex = activeBoundTextureForTexImageTarget(target);
|
||||
MOZ_ASSERT(tex != nullptr, "no texture bound");
|
||||
|
||||
bool sizeMayChange = true;
|
||||
|
@ -3633,7 +3641,7 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
|||
return ErrorInvalidOperation("texImage2D: not enough data for operation (need %d, have %d)",
|
||||
bytesNeeded, byteLength);
|
||||
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture *tex = activeBoundTextureForTexImageTarget(target);
|
||||
|
||||
if (!tex)
|
||||
return ErrorInvalidOperation("texImage2D: no texture is bound to this target");
|
||||
|
@ -3789,7 +3797,7 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
|
|||
if (byteLength < bytesNeeded)
|
||||
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
|
||||
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture *tex = activeBoundTextureForTexImageTarget(target);
|
||||
const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(target, level);
|
||||
|
||||
if (imageInfo.HasUninitializedImageData())
|
||||
|
|
|
@ -56,6 +56,24 @@ FormatHasAlpha(GLenum webGLFormat)
|
|||
webGLFormat == LOCAL_GL_SRGB_ALPHA;
|
||||
}
|
||||
|
||||
GLenum
|
||||
TexImageTargetToTexTarget(GLenum texImageTarget)
|
||||
{
|
||||
switch (texImageTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
return LOCAL_GL_TEXTURE_2D;
|
||||
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:
|
||||
return LOCAL_GL_TEXTURE_CUBE_MAP;
|
||||
default:
|
||||
return LOCAL_GL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
GLComponents::GLComponents(GLenum format)
|
||||
{
|
||||
mComponents = 0;
|
||||
|
|
|
@ -19,6 +19,20 @@ void DriverFormatsFromFormatAndType(gl::GLContext* gl, GLenum webGLFormat, GLenu
|
|||
GLenum* out_driverInternalFormat, GLenum* out_driverFormat);
|
||||
GLenum DriverTypeFromType(gl::GLContext* gl, GLenum webGLType);
|
||||
|
||||
// For use with the different texture calls, i.e.
|
||||
// TexImage2D, CopyTex[Sub]Image2D, ...
|
||||
// that take a "target" parameter. This parameter is not always the same as
|
||||
// the texture binding location, like GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP.
|
||||
// For example, cube maps would pass GL_TEXTURE_CUBE_MAP_[POS|NEG]_[X|Y|Z]
|
||||
// instead of just GL_TEXTURE_CUBE_MAP.
|
||||
//
|
||||
// This function converts the texture image target to the texture target a.k.a.
|
||||
// binding location. The returned binding location can be used to check that
|
||||
// the currently bound texture is appropriate for this texImageTarget.
|
||||
//
|
||||
// Returns GL_NONE if passed an invalid texture image target
|
||||
GLenum TexImageTargetToTexTarget(GLenum texImageTarget);
|
||||
|
||||
struct GLComponents
|
||||
{
|
||||
unsigned char mComponents;
|
||||
|
|
|
@ -1365,7 +1365,7 @@ WebGLContext::ValidateTexImage(GLuint dims, GLenum target,
|
|||
* WebGLTexture bound (see above), an INVALID_OPERATION error
|
||||
* is generated."
|
||||
*/
|
||||
WebGLTexture* tex = activeBoundTextureForTarget(target);
|
||||
WebGLTexture* tex = activeBoundTextureForTexImageTarget(target);
|
||||
if (!tex) {
|
||||
ErrorInvalidOperation("%s: no texture is bound to target %s",
|
||||
info, WebGLContext::EnumName(target));
|
||||
|
@ -1735,6 +1735,19 @@ WebGLContext::InitAndValidateGL()
|
|||
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
|
||||
}
|
||||
|
||||
// Calculate log2 of mGLMaxTextureSize and mGLMaxCubeMapTextureSize
|
||||
mGLMaxTextureSizeLog2 = 0;
|
||||
int32_t tempSize = mGLMaxTextureSize;
|
||||
while (tempSize >>= 1) {
|
||||
++mGLMaxTextureSizeLog2;
|
||||
}
|
||||
|
||||
mGLMaxCubeMapTextureSizeLog2 = 0;
|
||||
tempSize = mGLMaxCubeMapTextureSize;
|
||||
while (tempSize >>= 1) {
|
||||
++mGLMaxCubeMapTextureSizeLog2;
|
||||
}
|
||||
|
||||
mGLMaxTextureSize = floorPOT(mGLMaxTextureSize);
|
||||
mGLMaxRenderbufferSize = floorPOT(mGLMaxRenderbufferSize);
|
||||
|
||||
|
|
|
@ -137,22 +137,17 @@ WebGLTexture::Bind(GLenum aTarget) {
|
|||
}
|
||||
|
||||
void
|
||||
WebGLTexture::SetImageInfo(GLenum aTarget, GLint aLevel,
|
||||
WebGLTexture::SetImageInfo(GLenum aTexImageTarget, GLint aLevel,
|
||||
GLsizei aWidth, GLsizei aHeight,
|
||||
GLenum aFormat, GLenum aType, WebGLImageDataStatus aStatus)
|
||||
{
|
||||
// TODO(djg): I suspected the following ASSERT and check are
|
||||
// trying to express more than they're saying, probably
|
||||
// to do with cubemap targets. We should do this
|
||||
// properly. https://bugzilla.mozilla.org/show_bug.cgi?id=1006908
|
||||
MOZ_ASSERT((aTarget == LOCAL_GL_TEXTURE_2D) == (mTarget == LOCAL_GL_TEXTURE_2D));
|
||||
if ((aTarget == LOCAL_GL_TEXTURE_2D) != (mTarget == LOCAL_GL_TEXTURE_2D)) {
|
||||
MOZ_ASSERT(TexImageTargetToTexTarget(aTexImageTarget) == mTarget);
|
||||
if (TexImageTargetToTexTarget(aTexImageTarget) != mTarget)
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureMaxLevelWithCustomImagesAtLeast(aLevel);
|
||||
|
||||
ImageInfoAt(aTarget, aLevel) = ImageInfo(aWidth, aHeight, aFormat, aType, aStatus);
|
||||
ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aFormat, aType, aStatus);
|
||||
|
||||
if (aLevel > 0)
|
||||
SetCustomMipmap();
|
||||
|
|
Загрузка…
Ссылка в новой задаче