mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Back out changeset 2f614bcd9405 (bug 1221822) for test_conformance__extensions__ext-sRGB.html and test_webgl2_alpha_luminance.html failures
This commit is contained in:
parent
a4e1fa37a6
commit
71a6f5da62
@ -983,7 +983,7 @@ nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
|
||||
{
|
||||
// get the widget to send the event to
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
|
||||
|
||||
return nsContentUtils::SendKeyEvent(widget, aType, aKeyCode, aCharCode,
|
||||
aModifiers, aAdditionalFlags,
|
||||
aDefaultActionTaken);
|
||||
@ -1312,7 +1312,7 @@ nsDOMWindowUtils::NodesFromRect(float aX, float aY,
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
NS_ENSURE_STATE(doc);
|
||||
|
||||
return doc->NodesFromRectHelper(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
|
||||
return doc->NodesFromRectHelper(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
|
||||
aIgnoreRootScrollFrame, aFlushLayout, aReturn);
|
||||
}
|
||||
|
||||
@ -1408,9 +1408,7 @@ CanvasToDataSourceSurface(nsIDOMHTMLCanvasElement* aCanvas)
|
||||
"be an element.");
|
||||
nsLayoutUtils::SurfaceFromElementResult result =
|
||||
nsLayoutUtils::SurfaceFromElement(node->AsElement());
|
||||
|
||||
MOZ_ASSERT(result.GetSourceSurface());
|
||||
return result.GetSourceSurface()->GetDataSurface();
|
||||
return result.mSourceSurface->GetDataSurface();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1751,7 +1749,7 @@ nsDOMWindowUtils::GetFullZoom(float* aFullZoom)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::DispatchDOMEventViaPresShell(nsIDOMNode* aTarget,
|
||||
nsIDOMEvent* aEvent,
|
||||
@ -2454,7 +2452,7 @@ nsDOMWindowUtils::RenderDocument(const nsRect& aRect,
|
||||
return presShell->RenderDocument(aRect, aFlags, aBackgroundColor, aThebesContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetCursorType(int16_t *aCursor)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCursor);
|
||||
|
@ -1209,8 +1209,8 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
|
||||
gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext()->MakeCurrent();
|
||||
gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext()->fDeleteTextures(1, &mVideoTexture);
|
||||
}
|
||||
mCurrentVideoSize.width = 0;
|
||||
mCurrentVideoSize.height = 0;
|
||||
mCurrentVideoSize.width = 0;
|
||||
mCurrentVideoSize.height = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2113,14 +2113,15 @@ CanvasRenderingContext2D::CreatePattern(const CanvasImageSource& source,
|
||||
nsLayoutUtils::SurfaceFromElement(htmlElement,
|
||||
nsLayoutUtils::SFE_WANT_FIRST_FRAME, mTarget);
|
||||
|
||||
if (!res.GetSourceSurface()) {
|
||||
if (!res.mSourceSurface) {
|
||||
error.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CanvasPattern> pat = new CanvasPattern(this, res.GetSourceSurface(), repeatMode,
|
||||
res.mPrincipal, res.mIsWriteOnly,
|
||||
res.mCORSUsed);
|
||||
RefPtr<CanvasPattern> pat =
|
||||
new CanvasPattern(this, res.mSourceSurface, repeatMode, res.mPrincipal,
|
||||
res.mIsWriteOnly, res.mCORSUsed);
|
||||
|
||||
return pat.forget();
|
||||
}
|
||||
|
||||
@ -5406,9 +5407,9 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
|
||||
uint8_t* srcLine = aArray->Data() + copyY * (w * 4) + copyX * 4;
|
||||
#if 0
|
||||
printf("PutImageData_explicit: dirty x=%d y=%d w=%d h=%d copy x=%d y=%d w=%d h=%d ext x=%d y=%d w=%d h=%d\n",
|
||||
dirtyRect.x, dirtyRect.y, copyWidth, copyHeight,
|
||||
copyX, copyY, copyWidth, copyHeight,
|
||||
x, y, w, h);
|
||||
dirtyRect.x, dirtyRect.y, copyWidth, copyHeight,
|
||||
copyX, copyY, copyWidth, copyHeight,
|
||||
x, y, w, h);
|
||||
#endif
|
||||
for (uint32_t j = 0; j < copyHeight; j++) {
|
||||
uint8_t *src = srcLine;
|
||||
|
@ -355,13 +355,12 @@ GetSurfaceFromElement(nsIGlobalObject* aGlobal, HTMLElementType& aElement, Error
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> surface = res.GetSourceSurface();
|
||||
|
||||
if (NS_WARN_IF(!surface)) {
|
||||
if (NS_WARN_IF(!res.mSourceSurface)) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> surface(res.mSourceSurface);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
|
@ -1,773 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TexUnpackBlob.h"
|
||||
|
||||
#include "GLBlitHelper.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLDefs.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLTexelConversions.h"
|
||||
#include "WebGLTexture.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
static GLenum
|
||||
DoTexOrSubImage(bool isSubImage, gl::GLContext* gl, TexImageTarget target, GLint level,
|
||||
const DriverUnpackInfo* dui, GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth, const void* data)
|
||||
{
|
||||
if (isSubImage) {
|
||||
return DoTexSubImage(gl, target, level, xOffset, yOffset, zOffset, width, height,
|
||||
depth, dui->ToPacking(), data);
|
||||
} else {
|
||||
return DoTexImage(gl, target, level, dui, width, height, depth, data);
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
TexUnpackBlob::OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
|
||||
gl::OriginPos* const out_dst)
|
||||
{
|
||||
// Our surfaces are TopLeft.
|
||||
*out_src = gl::OriginPos::TopLeft;
|
||||
|
||||
// WebGL specs the default as passing DOM elements top-left first.
|
||||
// Thus y-flip would give us bottom-left.
|
||||
*out_dst = webgl->mPixelStore_FlipY ? gl::OriginPos::BottomLeft
|
||||
: gl::OriginPos::TopLeft;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackBytes
|
||||
|
||||
bool
|
||||
TexUnpackBytes::ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi)
|
||||
{
|
||||
if (!mBytes)
|
||||
return true;
|
||||
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
const auto bytesNeeded = webgl->GetUnpackSize(isFunc3D, mWidth, mHeight, mDepth,
|
||||
bytesPerPixel);
|
||||
if (!bytesNeeded.isValid()) {
|
||||
webgl->ErrorInvalidOperation("%s: Overflow while computing the needed buffer"
|
||||
" size.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mByteCount < bytesNeeded.value()) {
|
||||
webgl->ErrorInvalidOperation("%s: Provided buffer is too small. (needs %u, has"
|
||||
" %u)",
|
||||
funcName, bytesNeeded.value(), mByteCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
UnpackFormatHasAlpha(GLenum unpackFormat)
|
||||
{
|
||||
switch (unpackFormat) {
|
||||
case LOCAL_GL_ALPHA:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
case LOCAL_GL_RGBA:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static WebGLTexelFormat
|
||||
FormatFromPacking(const webgl::PackingInfo& pi)
|
||||
{
|
||||
switch (pi.type) {
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||
return WebGLTexelFormat::RGB565;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
return WebGLTexelFormat::RGBA5551;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
return WebGLTexelFormat::RGBA4444;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
switch (pi.format) {
|
||||
case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R8;
|
||||
case LOCAL_GL_ALPHA: return WebGLTexelFormat::A8;
|
||||
case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA8;
|
||||
case LOCAL_GL_RGB: return WebGLTexelFormat::RGB8;
|
||||
case LOCAL_GL_SRGB: return WebGLTexelFormat::RGB8;
|
||||
case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA8;
|
||||
case LOCAL_GL_SRGB_ALPHA: return WebGLTexelFormat::RGBA8;
|
||||
}
|
||||
|
||||
case LOCAL_GL_HALF_FLOAT:
|
||||
case LOCAL_GL_HALF_FLOAT_OES:
|
||||
switch (pi.format) {
|
||||
case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R16F;
|
||||
case LOCAL_GL_ALPHA: return WebGLTexelFormat::A16F;
|
||||
case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA16F;
|
||||
case LOCAL_GL_RGB: return WebGLTexelFormat::RGB16F;
|
||||
case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA16F;
|
||||
}
|
||||
|
||||
case LOCAL_GL_FLOAT:
|
||||
switch (pi.format) {
|
||||
case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R32F;
|
||||
case LOCAL_GL_ALPHA: return WebGLTexelFormat::A32F;
|
||||
case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA32F;
|
||||
case LOCAL_GL_RGB: return WebGLTexelFormat::RGB32F;
|
||||
case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA32F;
|
||||
}
|
||||
}
|
||||
|
||||
return WebGLTexelFormat::FormatNotSupportingAnyConversion;
|
||||
}
|
||||
|
||||
void
|
||||
TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum* const out_glError)
|
||||
{
|
||||
WebGLContext* webgl = tex->mContext;
|
||||
gl::GLContext* gl = webgl->gl;
|
||||
|
||||
const void* uploadBytes = mBytes;
|
||||
UniqueBuffer tempBuffer;
|
||||
|
||||
do {
|
||||
if (!webgl->mPixelStore_FlipY && !webgl->mPixelStore_PremultiplyAlpha)
|
||||
break;
|
||||
|
||||
if (!mBytes || !mWidth || !mHeight || !mDepth)
|
||||
break;
|
||||
|
||||
if (webgl->IsWebGL2())
|
||||
break;
|
||||
MOZ_ASSERT(mDepth == 1);
|
||||
|
||||
// This is literally the worst.
|
||||
webgl->GenerateWarning("%s: Uploading ArrayBuffers with FLIP_Y or"
|
||||
" PREMULTIPLY_ALPHA is slow.",
|
||||
funcName);
|
||||
|
||||
tempBuffer = malloc(mByteCount);
|
||||
if (!tempBuffer) {
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
const webgl::PackingInfo pi = { dui->unpackFormat, dui->unpackType };
|
||||
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
const auto rowByteAlignment = webgl->mPixelStore_UnpackAlignment;
|
||||
|
||||
const size_t bytesPerRow = bytesPerPixel * mWidth;
|
||||
const size_t rowStride = RoundUpToMultipleOf(bytesPerRow, rowByteAlignment);
|
||||
|
||||
const bool needsYFlip = webgl->mPixelStore_FlipY;
|
||||
|
||||
bool needsAlphaPremult = webgl->mPixelStore_PremultiplyAlpha;
|
||||
if (!UnpackFormatHasAlpha(pi.format))
|
||||
needsAlphaPremult = false;
|
||||
|
||||
if (!needsAlphaPremult) {
|
||||
if (!webgl->mPixelStore_FlipY)
|
||||
break;
|
||||
|
||||
const uint8_t* src = (const uint8_t*)mBytes;
|
||||
const uint8_t* const srcEnd = src + rowStride * mHeight;
|
||||
|
||||
uint8_t* dst = (uint8_t*)tempBuffer.get() + rowStride * (mHeight - 1);
|
||||
|
||||
while (src != srcEnd) {
|
||||
memcpy(dst, src, bytesPerRow);
|
||||
src += rowStride;
|
||||
dst -= rowStride;
|
||||
}
|
||||
|
||||
uploadBytes = tempBuffer.get();
|
||||
break;
|
||||
}
|
||||
|
||||
const auto texelFormat = FormatFromPacking(pi);
|
||||
if (texelFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion) {
|
||||
MOZ_ASSERT(false, "Bad texelFormat from pi.");
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto srcOrigin = gl::OriginPos::BottomLeft;
|
||||
const auto dstOrigin = (needsYFlip ? gl::OriginPos::TopLeft
|
||||
: gl::OriginPos::BottomLeft);
|
||||
|
||||
const bool srcPremultiplied = false;
|
||||
const bool dstPremultiplied = needsAlphaPremult; // Always true here.
|
||||
// And go!:
|
||||
if (!ConvertImage(mWidth, mHeight,
|
||||
mBytes, rowStride, srcOrigin, texelFormat, srcPremultiplied,
|
||||
tempBuffer.get(), rowStride, dstOrigin, texelFormat,
|
||||
dstPremultiplied))
|
||||
{
|
||||
MOZ_ASSERT(false, "ConvertImage failed unexpectedly.");
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
uploadBytes = tempBuffer.get();
|
||||
} while (false);
|
||||
|
||||
GLenum error = DoTexOrSubImage(isSubImage, gl, target, level, dui, xOffset, yOffset,
|
||||
zOffset, mWidth, mHeight, mDepth, uploadBytes);
|
||||
*out_glError = error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackImage
|
||||
|
||||
TexUnpackImage::TexUnpackImage(const RefPtr<layers::Image>& image, bool isAlphaPremult)
|
||||
: TexUnpackBlob(image->GetSize().width, image->GetSize().height, 1, true)
|
||||
, mImage(image)
|
||||
, mIsAlphaPremult(isAlphaPremult)
|
||||
{ }
|
||||
|
||||
TexUnpackImage::~TexUnpackImage()
|
||||
{ }
|
||||
|
||||
void
|
||||
TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum* const out_glError)
|
||||
{
|
||||
MOZ_ASSERT_IF(needsRespec, !isSubImage);
|
||||
*out_glError = 0;
|
||||
|
||||
WebGLContext* webgl = tex->mContext;
|
||||
|
||||
gl::GLContext* gl = webgl->GL();
|
||||
gl->MakeCurrent();
|
||||
|
||||
if (needsRespec) {
|
||||
GLenum error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
|
||||
yOffset, zOffset, mWidth, mHeight, mDepth,
|
||||
nullptr);
|
||||
if (error) {
|
||||
MOZ_ASSERT(!error);
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
if (dui->unpackFormat != LOCAL_GL_RGB && dui->unpackFormat != LOCAL_GL_RGBA)
|
||||
break;
|
||||
|
||||
if (dui->unpackType != LOCAL_GL_UNSIGNED_BYTE)
|
||||
break;
|
||||
|
||||
gl::ScopedFramebuffer scopedFB(gl);
|
||||
gl::ScopedBindFramebuffer bindFB(gl, scopedFB.FB());
|
||||
|
||||
{
|
||||
gl::GLContext::LocalErrorScope errorScope(*gl);
|
||||
|
||||
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
target.get(), tex->mGLName, level);
|
||||
|
||||
if (errorScope.GetError())
|
||||
break;
|
||||
}
|
||||
|
||||
const GLenum status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
break;
|
||||
|
||||
gl::OriginPos srcOrigin, dstOrigin;
|
||||
OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
|
||||
|
||||
const gfx::IntSize destSize(mWidth, mHeight);
|
||||
if (!gl->BlitHelper()->BlitImageToFramebuffer(mImage, destSize, scopedFB.FB(),
|
||||
dstOrigin))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
return; // Blitting was successful, so we're done!
|
||||
} while (false);
|
||||
|
||||
TexUnpackSurface surfBlob(mImage->GetAsSourceSurface(), mIsAlphaPremult);
|
||||
|
||||
surfBlob.TexOrSubImage(isSubImage, needsRespec, funcName, tex, target, level, dui,
|
||||
xOffset, yOffset, zOffset, out_glError);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackSurface
|
||||
|
||||
static bool
|
||||
GuessAlignment(const void* data, size_t bytesPerRow, size_t stride, size_t maxAlignment,
|
||||
size_t* const out_alignment)
|
||||
{
|
||||
size_t alignmentGuess = maxAlignment;
|
||||
while (alignmentGuess) {
|
||||
size_t guessStride = RoundUpToMultipleOf(bytesPerRow, alignmentGuess);
|
||||
if (guessStride == stride &&
|
||||
uintptr_t(data) % alignmentGuess == 0)
|
||||
{
|
||||
*out_alignment = alignmentGuess;
|
||||
return true;
|
||||
}
|
||||
alignmentGuess /= 2;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
SupportsBGRA(gl::GLContext* gl)
|
||||
{
|
||||
if (gl->IsANGLE())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
TexUnpackSurface::UploadDataSurface(bool isSubImage, WebGLContext* webgl,
|
||||
TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLsizei width,
|
||||
GLsizei height, gfx::DataSourceSurface* surf,
|
||||
bool isSurfAlphaPremult, GLenum* const out_glError)
|
||||
{
|
||||
gl::GLContext* gl = webgl->GL();
|
||||
MOZ_ASSERT(gl->IsCurrent());
|
||||
*out_glError = 0;
|
||||
|
||||
if (isSurfAlphaPremult != webgl->mPixelStore_PremultiplyAlpha)
|
||||
return false;
|
||||
|
||||
gl::OriginPos srcOrigin, dstOrigin;
|
||||
OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
|
||||
if (srcOrigin != dstOrigin)
|
||||
return false;
|
||||
|
||||
// This differs from the raw-data upload in that we choose how we do the unpack.
|
||||
// (alignment, etc.)
|
||||
|
||||
// Uploading RGBX as RGBA and blitting to RGB is faster than repacking RGBX into
|
||||
// RGB on the CPU. However, this is optimization is out-of-scope for now.
|
||||
|
||||
static const webgl::DriverUnpackInfo kInfoBGRA = {
|
||||
LOCAL_GL_BGRA,
|
||||
LOCAL_GL_BGRA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
};
|
||||
|
||||
const webgl::DriverUnpackInfo* chosenDUI = nullptr;
|
||||
|
||||
switch (surf->GetFormat()) {
|
||||
case gfx::SurfaceFormat::B8G8R8A8:
|
||||
if (SupportsBGRA(gl) &&
|
||||
dui->internalFormat == LOCAL_GL_RGBA &&
|
||||
dui->unpackFormat == LOCAL_GL_RGBA &&
|
||||
dui->unpackType == LOCAL_GL_UNSIGNED_BYTE)
|
||||
{
|
||||
chosenDUI = &kInfoBGRA;
|
||||
}
|
||||
break;
|
||||
|
||||
case gfx::SurfaceFormat::R8G8B8A8:
|
||||
if (dui->unpackFormat == LOCAL_GL_RGBA &&
|
||||
dui->unpackType == LOCAL_GL_UNSIGNED_BYTE)
|
||||
{
|
||||
chosenDUI = dui;
|
||||
}
|
||||
break;
|
||||
|
||||
case gfx::SurfaceFormat::R5G6B5_UINT16:
|
||||
if (dui->unpackFormat == LOCAL_GL_RGB &&
|
||||
dui->unpackType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
|
||||
{
|
||||
chosenDUI = dui;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!chosenDUI)
|
||||
return false;
|
||||
|
||||
gfx::DataSourceSurface::ScopedMap map(surf, gfx::DataSourceSurface::MapType::READ);
|
||||
if (!map.IsMapped())
|
||||
return false;
|
||||
|
||||
const webgl::PackingInfo pi = {chosenDUI->unpackFormat, chosenDUI->unpackType};
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
const size_t bytesPerRow = width * bytesPerPixel;
|
||||
|
||||
const GLint kMaxUnpackAlignment = 8;
|
||||
size_t unpackAlignment;
|
||||
if (!GuessAlignment(map.GetData(), bytesPerRow, map.GetStride(), kMaxUnpackAlignment,
|
||||
&unpackAlignment))
|
||||
{
|
||||
return false;
|
||||
// TODO: Consider using UNPACK_ settings to set the stride based on the too-large
|
||||
// alignment used for some SourceSurfaces. (D2D allegedy likes alignment=16)
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
|
||||
ScopedUnpackReset scopedReset(webgl);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, unpackAlignment);
|
||||
|
||||
const GLsizei depth = 1;
|
||||
GLenum error = DoTexOrSubImage(isSubImage, gl, target.get(), level, chosenDUI,
|
||||
xOffset, yOffset, zOffset, width, height, depth,
|
||||
map.GetData());
|
||||
if (error) {
|
||||
*out_glError = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
static bool
|
||||
GetFormatForSurf(gfx::SourceSurface* surf, WebGLTexelFormat* const out_texelFormat)
|
||||
{
|
||||
gfx::SurfaceFormat surfFormat = surf->GetFormat();
|
||||
|
||||
switch (surfFormat) {
|
||||
case gfx::SurfaceFormat::B8G8R8A8:
|
||||
*out_texelFormat = WebGLTexelFormat::BGRA8;
|
||||
return true;
|
||||
|
||||
case gfx::SurfaceFormat::B8G8R8X8:
|
||||
*out_texelFormat = WebGLTexelFormat::BGRX8;
|
||||
return true;
|
||||
|
||||
case gfx::SurfaceFormat::R8G8B8A8:
|
||||
*out_texelFormat = WebGLTexelFormat::RGBA8;
|
||||
return true;
|
||||
|
||||
case gfx::SurfaceFormat::R8G8B8X8:
|
||||
*out_texelFormat = WebGLTexelFormat::RGBX8;
|
||||
return true;
|
||||
|
||||
case gfx::SurfaceFormat::R5G6B5_UINT16:
|
||||
*out_texelFormat = WebGLTexelFormat::RGB565;
|
||||
return true;
|
||||
|
||||
case gfx::SurfaceFormat::A8:
|
||||
*out_texelFormat = WebGLTexelFormat::A8;
|
||||
return true;
|
||||
|
||||
case gfx::SurfaceFormat::YUV:
|
||||
// Ugh...
|
||||
NS_ERROR("We don't handle uploads from YUV sources yet.");
|
||||
// When we want to, check out gfx/ycbcr/YCbCrUtils.h. (specifically
|
||||
// GetYCbCrToRGBDestFormatAndSize and ConvertYCbCrToRGB)
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
GetFormatForPackingTuple(GLenum packingFormat, GLenum packingType,
|
||||
WebGLTexelFormat* const out_texelFormat)
|
||||
{
|
||||
switch (packingType) {
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
switch (packingFormat) {
|
||||
case LOCAL_GL_RED:
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
*out_texelFormat = WebGLTexelFormat::R8;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_ALPHA:
|
||||
*out_texelFormat = WebGLTexelFormat::A8;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
*out_texelFormat = WebGLTexelFormat::RA8;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_RGB:
|
||||
*out_texelFormat = WebGLTexelFormat::RGB8;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_RGBA:
|
||||
*out_texelFormat = WebGLTexelFormat::RGBA8;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||
switch (packingFormat) {
|
||||
case LOCAL_GL_RGB:
|
||||
*out_texelFormat = WebGLTexelFormat::RGB565;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
switch (packingFormat) {
|
||||
case LOCAL_GL_RGBA:
|
||||
*out_texelFormat = WebGLTexelFormat::RGBA5551;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
switch (packingFormat) {
|
||||
case LOCAL_GL_RGBA:
|
||||
*out_texelFormat = WebGLTexelFormat::RGBA4444;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_HALF_FLOAT:
|
||||
case LOCAL_GL_HALF_FLOAT_OES:
|
||||
switch (packingFormat) {
|
||||
case LOCAL_GL_RED:
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
*out_texelFormat = WebGLTexelFormat::R16F;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_ALPHA:
|
||||
*out_texelFormat = WebGLTexelFormat::A16F;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
*out_texelFormat = WebGLTexelFormat::RA16F;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_RGB:
|
||||
*out_texelFormat = WebGLTexelFormat::RGB16F;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_RGBA:
|
||||
*out_texelFormat = WebGLTexelFormat::RGBA16F;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_FLOAT:
|
||||
switch (packingFormat) {
|
||||
case LOCAL_GL_RED:
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
*out_texelFormat = WebGLTexelFormat::R32F;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_ALPHA:
|
||||
*out_texelFormat = WebGLTexelFormat::A32F;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
*out_texelFormat = WebGLTexelFormat::RA32F;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_RGB:
|
||||
*out_texelFormat = WebGLTexelFormat::RGB32F;
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_RGBA:
|
||||
*out_texelFormat = WebGLTexelFormat::RGBA32F;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
NS_ERROR("Unsupported EffectiveFormat dest format for DOM element upload.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
TexUnpackSurface::ConvertSurface(WebGLContext* webgl, const webgl::DriverUnpackInfo* dui,
|
||||
gfx::DataSourceSurface* surf, bool isSurfAlphaPremult,
|
||||
UniqueBuffer* const out_convertedBuffer,
|
||||
uint8_t* const out_convertedAlignment,
|
||||
bool* const out_outOfMemory)
|
||||
{
|
||||
*out_outOfMemory = false;
|
||||
|
||||
const size_t width = surf->GetSize().width;
|
||||
const size_t height = surf->GetSize().height;
|
||||
|
||||
// Source args:
|
||||
|
||||
// After we call this, on OSX, our GLContext will no longer be current.
|
||||
gfx::DataSourceSurface::ScopedMap srcMap(surf, gfx::DataSourceSurface::MapType::READ);
|
||||
if (!srcMap.IsMapped())
|
||||
return false;
|
||||
|
||||
const void* const srcBegin = srcMap.GetData();
|
||||
const size_t srcStride = srcMap.GetStride();
|
||||
|
||||
WebGLTexelFormat srcFormat;
|
||||
if (!GetFormatForSurf(surf, &srcFormat))
|
||||
return false;
|
||||
|
||||
const bool srcPremultiplied = isSurfAlphaPremult;
|
||||
|
||||
// Dest args:
|
||||
|
||||
WebGLTexelFormat dstFormat;
|
||||
if (!GetFormatForPackingTuple(dui->unpackFormat, dui->unpackType, &dstFormat))
|
||||
return false;
|
||||
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel({dui->unpackFormat, dui->unpackType});
|
||||
const size_t dstRowBytes = bytesPerPixel * width;
|
||||
|
||||
const size_t dstAlignment = 8; // Just use the max!
|
||||
const size_t dstStride = RoundUpToMultipleOf(dstRowBytes, dstAlignment);
|
||||
|
||||
CheckedUint32 checkedDstSize = dstStride;
|
||||
checkedDstSize *= height;
|
||||
if (!checkedDstSize.isValid()) {
|
||||
*out_outOfMemory = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t dstSize = checkedDstSize.value();
|
||||
|
||||
UniqueBuffer dstBuffer = malloc(dstSize);
|
||||
if (!dstBuffer) {
|
||||
*out_outOfMemory = true;
|
||||
return false;
|
||||
}
|
||||
void* const dstBegin = dstBuffer.get();
|
||||
|
||||
gl::OriginPos srcOrigin, dstOrigin;
|
||||
OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
|
||||
|
||||
const bool dstPremultiplied = webgl->mPixelStore_PremultiplyAlpha;
|
||||
|
||||
// And go!:
|
||||
if (!ConvertImage(width, height,
|
||||
srcBegin, srcStride, srcOrigin, srcFormat, srcPremultiplied,
|
||||
dstBegin, dstStride, dstOrigin, dstFormat, dstPremultiplied))
|
||||
{
|
||||
MOZ_ASSERT(false, "ConvertImage failed unexpectedly.");
|
||||
NS_ERROR("ConvertImage failed unexpectedly.");
|
||||
*out_outOfMemory = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_convertedBuffer = Move(dstBuffer);
|
||||
*out_convertedAlignment = dstAlignment;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////
|
||||
|
||||
TexUnpackSurface::TexUnpackSurface(const RefPtr<gfx::SourceSurface>& surf,
|
||||
bool isAlphaPremult)
|
||||
: TexUnpackBlob(surf->GetSize().width, surf->GetSize().height, 1, true)
|
||||
, mSurf(surf)
|
||||
, mIsAlphaPremult(isAlphaPremult)
|
||||
{ }
|
||||
|
||||
TexUnpackSurface::~TexUnpackSurface()
|
||||
{ }
|
||||
|
||||
void
|
||||
TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum* const out_glError)
|
||||
{
|
||||
*out_glError = 0;
|
||||
|
||||
WebGLContext* webgl = tex->mContext;
|
||||
|
||||
// MakeCurrent is a big mess in here, because mapping (and presumably unmapping) on
|
||||
// OSX can lose our MakeCurrent. Therefore it's easiest to MakeCurrent just before we
|
||||
// call into GL, instead of trying to keep MakeCurrent-ed.
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> dataSurf = mSurf->GetDataSurface();
|
||||
MOZ_ASSERT(dataSurf);
|
||||
|
||||
GLenum error;
|
||||
if (UploadDataSurface(isSubImage, webgl, target, level, dui, xOffset, yOffset,
|
||||
zOffset, mWidth, mHeight, dataSurf, mIsAlphaPremult, &error))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (error == LOCAL_GL_OUT_OF_MEMORY) {
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
// CPU conversion. (++numCopies)
|
||||
|
||||
UniqueBuffer convertedBuffer;
|
||||
uint8_t convertedAlignment;
|
||||
bool outOfMemory;
|
||||
if (!ConvertSurface(webgl, dui, dataSurf, mIsAlphaPremult, &convertedBuffer,
|
||||
&convertedAlignment, &outOfMemory))
|
||||
{
|
||||
if (outOfMemory) {
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
} else {
|
||||
NS_ERROR("Failed to convert surface.");
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
|
||||
ScopedUnpackReset scopedReset(webgl);
|
||||
webgl->gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, convertedAlignment);
|
||||
|
||||
error = DoTexOrSubImage(isSubImage, webgl->gl, target.get(), level, dui, xOffset,
|
||||
yOffset, zOffset, mWidth, mHeight, mDepth,
|
||||
convertedBuffer.get());
|
||||
*out_glError = error;
|
||||
}
|
||||
|
||||
} // namespace webgl
|
||||
} // namespace mozilla
|
@ -1,162 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef TEX_UNPACK_BLOB_H_
|
||||
#define TEX_UNPACK_BLOB_H_
|
||||
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLTypes.h"
|
||||
#include "WebGLStrongTypes.h"
|
||||
|
||||
|
||||
template <class T>
|
||||
class RefPtr;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class UniqueBuffer;
|
||||
class WebGLContext;
|
||||
class WebGLTexture;
|
||||
|
||||
namespace dom {
|
||||
class Element;
|
||||
class HTMLCanvasElement;
|
||||
class HTMLVideoElement;
|
||||
} // namespace dom
|
||||
|
||||
namespace gfx {
|
||||
class DataSourceSurface;
|
||||
} // namespace gfx
|
||||
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
} // namespace gl
|
||||
|
||||
namespace layers {
|
||||
class Image;
|
||||
class ImageContainer;
|
||||
} // namespace layers
|
||||
|
||||
namespace webgl {
|
||||
|
||||
struct PackingInfo;
|
||||
struct DriverUnpackInfo;
|
||||
|
||||
class TexUnpackBlob
|
||||
{
|
||||
public:
|
||||
const GLsizei mWidth;
|
||||
const GLsizei mHeight;
|
||||
const GLsizei mDepth;
|
||||
const bool mHasData;
|
||||
|
||||
protected:
|
||||
TexUnpackBlob(GLsizei width, GLsizei height, GLsizei depth, bool hasData)
|
||||
: mWidth(width)
|
||||
, mHeight(height)
|
||||
, mDepth(depth)
|
||||
, mHasData(hasData)
|
||||
{ }
|
||||
|
||||
public:
|
||||
virtual ~TexUnpackBlob() {}
|
||||
|
||||
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi) = 0;
|
||||
|
||||
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_glError) = 0;
|
||||
|
||||
static void OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
|
||||
gl::OriginPos* const out_dst);
|
||||
};
|
||||
|
||||
class TexUnpackBytes : public TexUnpackBlob
|
||||
{
|
||||
public:
|
||||
const size_t mByteCount;
|
||||
const void* const mBytes;
|
||||
|
||||
TexUnpackBytes(GLsizei width, GLsizei height, GLsizei depth, size_t byteCount,
|
||||
const void* bytes)
|
||||
: TexUnpackBlob(width, height, depth, bool(bytes))
|
||||
, mByteCount(byteCount)
|
||||
, mBytes(bytes)
|
||||
{ }
|
||||
|
||||
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi) override;
|
||||
|
||||
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_glError) override;
|
||||
};
|
||||
|
||||
class TexUnpackImage : public TexUnpackBlob
|
||||
{
|
||||
public:
|
||||
const RefPtr<layers::Image> mImage;
|
||||
const bool mIsAlphaPremult;
|
||||
|
||||
TexUnpackImage(const RefPtr<layers::Image>& image, bool isAlphaPremult);
|
||||
virtual ~TexUnpackImage() override;
|
||||
|
||||
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_glError) override;
|
||||
};
|
||||
|
||||
class TexUnpackSurface : public TexUnpackBlob
|
||||
{
|
||||
public:
|
||||
const RefPtr<gfx::SourceSurface> mSurf;
|
||||
const bool mIsAlphaPremult;
|
||||
|
||||
TexUnpackSurface(const RefPtr<gfx::SourceSurface>& surf, bool isAlphaPremult);
|
||||
virtual ~TexUnpackSurface() override;
|
||||
|
||||
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_glError) override;
|
||||
|
||||
protected:
|
||||
static bool ConvertSurface(WebGLContext* webgl, const webgl::DriverUnpackInfo* dui,
|
||||
gfx::DataSourceSurface* surf, bool isSurfAlphaPremult,
|
||||
UniqueBuffer* const out_convertedBuffer,
|
||||
uint8_t* const out_convertedAlignment,
|
||||
bool* const out_outOfMemory);
|
||||
static bool UploadDataSurface(bool isSubImage, WebGLContext* webgl,
|
||||
TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLsizei width,
|
||||
GLsizei height, gfx::DataSourceSurface* surf,
|
||||
bool isSurfAlphaPremult, GLenum* const out_glError);
|
||||
};
|
||||
|
||||
} // namespace webgl
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // TEX_UNPACK_BLOB_H_
|
@ -27,9 +27,9 @@ WebGL1Context::~WebGL1Context()
|
||||
}
|
||||
|
||||
UniquePtr<webgl::FormatUsageAuthority>
|
||||
WebGL1Context::CreateFormatUsage(gl::GLContext* gl) const
|
||||
WebGL1Context::CreateFormatUsage() const
|
||||
{
|
||||
return webgl::FormatUsageAuthority::CreateForWebGL1(gl);
|
||||
return webgl::FormatUsageAuthority::CreateForWebGL1();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -18,9 +18,7 @@ public:
|
||||
|
||||
private:
|
||||
WebGL1Context();
|
||||
|
||||
virtual UniquePtr<webgl::FormatUsageAuthority>
|
||||
CreateFormatUsage(gl::GLContext* gl) const override;
|
||||
virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage() const override;
|
||||
|
||||
public:
|
||||
virtual ~WebGL1Context();
|
||||
|
@ -29,9 +29,9 @@ WebGL2Context::~WebGL2Context()
|
||||
}
|
||||
|
||||
UniquePtr<webgl::FormatUsageAuthority>
|
||||
WebGL2Context::CreateFormatUsage(gl::GLContext* gl) const
|
||||
WebGL2Context::CreateFormatUsage() const
|
||||
{
|
||||
return webgl::FormatUsageAuthority::CreateForWebGL2(gl);
|
||||
return webgl::FormatUsageAuthority::CreateForWebGL2();
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
@ -55,6 +55,20 @@ WebGL2Context::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// WebGL 2 initialisation
|
||||
|
||||
// These WebGL 1 extensions are natively supported by WebGL 2.
|
||||
static const WebGLExtensionID kNativelySupportedExtensions[] = {
|
||||
WebGLExtensionID::ANGLE_instanced_arrays,
|
||||
WebGLExtensionID::EXT_blend_minmax,
|
||||
WebGLExtensionID::EXT_sRGB,
|
||||
WebGLExtensionID::OES_element_index_uint,
|
||||
WebGLExtensionID::OES_standard_derivatives,
|
||||
WebGLExtensionID::OES_texture_float_linear,
|
||||
WebGLExtensionID::OES_texture_half_float_linear,
|
||||
WebGLExtensionID::OES_vertex_array_object,
|
||||
WebGLExtensionID::WEBGL_depth_texture,
|
||||
WebGLExtensionID::WEBGL_draw_buffers
|
||||
};
|
||||
|
||||
static const gl::GLFeature kRequiredFeatures[] = {
|
||||
gl::GLFeature::blend_minmax,
|
||||
gl::GLFeature::clear_buffers,
|
||||
@ -137,25 +151,35 @@ WebGLContext::InitWebGL2()
|
||||
return false;
|
||||
}
|
||||
|
||||
// ok WebGL 2 is compatible, we can enable natively supported extensions.
|
||||
for (size_t i = 0; i < ArrayLength(kNativelySupportedExtensions); i++) {
|
||||
EnableExtension(kNativelySupportedExtensions[i]);
|
||||
|
||||
MOZ_ASSERT(IsExtensionEnabled(kNativelySupportedExtensions[i]));
|
||||
}
|
||||
|
||||
// we initialise WebGL 2 related stuff.
|
||||
gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
|
||||
&mGLMaxTransformFeedbackSeparateAttribs);
|
||||
gl->GetUIntegerv(LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS,
|
||||
&mGLMaxUniformBufferBindings);
|
||||
|
||||
if (MinCapabilityMode()) {
|
||||
mGLMax3DTextureSize = MINVALUE_GL_MAX_3D_TEXTURE_SIZE;
|
||||
mGLMaxArrayTextureLayers = MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS;
|
||||
} else {
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_3D_TEXTURE_SIZE,
|
||||
(GLint*) &mGLMax3DTextureSize);
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS,
|
||||
(GLint*) &mGLMaxArrayTextureLayers);
|
||||
}
|
||||
|
||||
mBoundTransformFeedbackBuffers.SetLength(mGLMaxTransformFeedbackSeparateAttribs);
|
||||
mBoundUniformBuffers.SetLength(mGLMaxUniformBufferBindings);
|
||||
|
||||
mDefaultTransformFeedback = new WebGLTransformFeedback(this, 0);
|
||||
mBoundTransformFeedback = mDefaultTransformFeedback;
|
||||
|
||||
if (!gl->IsGLES()) {
|
||||
// Desktop OpenGL requires the following to be enabled in order to
|
||||
// support sRGB operations on framebuffers.
|
||||
gl->MakeCurrent();
|
||||
gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,12 @@
|
||||
|
||||
#include "WebGLContext.h"
|
||||
|
||||
/*
|
||||
* Minimum value constants define in 6.2 State Tables of OpenGL ES - 3.0.4
|
||||
*/
|
||||
#define MINVALUE_GL_MAX_3D_TEXTURE_SIZE 256
|
||||
#define MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS 256
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
@ -90,47 +96,37 @@ public:
|
||||
// -------------------------------------------------------------------------
|
||||
// Texture objects - WebGL2ContextTextures.cpp
|
||||
|
||||
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width,
|
||||
GLsizei height);
|
||||
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width,
|
||||
GLsizei height, GLsizei depth);
|
||||
void TexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels);
|
||||
void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
|
||||
ErrorResult& out_rv);
|
||||
void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::ImageData* data, ErrorResult& out_rv);
|
||||
protected:
|
||||
void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::Element* elem, ErrorResult* const out_rv);
|
||||
public:
|
||||
template<class T>
|
||||
inline void
|
||||
TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, T& elem, ErrorResult& out_rv)
|
||||
{
|
||||
TexSubImage3D(target, level, xOffset, yOffset, zOffset, unpackFormat, unpackType,
|
||||
&elem, &out_rv);
|
||||
}
|
||||
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
||||
GLsizei depth);
|
||||
void TexImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLenum format, GLenum type,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
|
||||
ErrorResult& rv);
|
||||
void TexSubImage3D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type, const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
|
||||
ErrorResult& rv);
|
||||
void TexSubImage3D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLenum format, GLenum type, dom::ImageData* data,
|
||||
ErrorResult& rv);
|
||||
template<class ElementType>
|
||||
void TexSubImage3D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLenum format, GLenum type, ElementType& elt, ErrorResult& rv)
|
||||
{}
|
||||
|
||||
void CopyTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
void CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
|
||||
void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& data);
|
||||
void CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLenum sizedUnpackFormat,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& data);
|
||||
GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data);
|
||||
void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -387,8 +383,7 @@ public:
|
||||
|
||||
private:
|
||||
WebGL2Context();
|
||||
virtual UniquePtr<webgl::FormatUsageAuthority>
|
||||
CreateFormatUsage(gl::GLContext* gl) const override;
|
||||
virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage() const override;
|
||||
|
||||
virtual bool IsTexParamValid(GLenum pname) const override;
|
||||
|
||||
|
@ -13,12 +13,107 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using gl::GLContext;
|
||||
using gl::GLFormats;
|
||||
using webgl::EffectiveFormat;
|
||||
using webgl::FormatInfo;
|
||||
using webgl::ComponentType;
|
||||
|
||||
// Returns one of FLOAT, INT, UNSIGNED_INT.
|
||||
// Fixed-points (normalized ints) are considered FLOAT.
|
||||
static GLenum
|
||||
ValueTypeForFormat(GLenum internalFormat)
|
||||
{
|
||||
switch (internalFormat) {
|
||||
// Fixed-point
|
||||
case LOCAL_GL_R8:
|
||||
case LOCAL_GL_RG8:
|
||||
case LOCAL_GL_RGB565:
|
||||
case LOCAL_GL_RGB8:
|
||||
case LOCAL_GL_RGBA4:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
case LOCAL_GL_RGBA8:
|
||||
case LOCAL_GL_RGB10_A2:
|
||||
case LOCAL_GL_ALPHA8:
|
||||
case LOCAL_GL_LUMINANCE8:
|
||||
case LOCAL_GL_LUMINANCE8_ALPHA8:
|
||||
case LOCAL_GL_SRGB8:
|
||||
case LOCAL_GL_SRGB8_ALPHA8:
|
||||
case LOCAL_GL_R8_SNORM:
|
||||
case LOCAL_GL_RG8_SNORM:
|
||||
case LOCAL_GL_RGB8_SNORM:
|
||||
case LOCAL_GL_RGBA8_SNORM:
|
||||
|
||||
// Floating-point
|
||||
case LOCAL_GL_R16F:
|
||||
case LOCAL_GL_RG16F:
|
||||
case LOCAL_GL_RGB16F:
|
||||
case LOCAL_GL_RGBA16F:
|
||||
case LOCAL_GL_ALPHA16F_EXT:
|
||||
case LOCAL_GL_LUMINANCE16F_EXT:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA16F_EXT:
|
||||
|
||||
case LOCAL_GL_R32F:
|
||||
case LOCAL_GL_RG32F:
|
||||
case LOCAL_GL_RGB32F:
|
||||
case LOCAL_GL_RGBA32F:
|
||||
case LOCAL_GL_ALPHA32F_EXT:
|
||||
case LOCAL_GL_LUMINANCE32F_EXT:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA32F_EXT:
|
||||
|
||||
case LOCAL_GL_R11F_G11F_B10F:
|
||||
case LOCAL_GL_RGB9_E5:
|
||||
return LOCAL_GL_FLOAT;
|
||||
|
||||
// Int
|
||||
case LOCAL_GL_R8I:
|
||||
case LOCAL_GL_RG8I:
|
||||
case LOCAL_GL_RGB8I:
|
||||
case LOCAL_GL_RGBA8I:
|
||||
|
||||
case LOCAL_GL_R16I:
|
||||
case LOCAL_GL_RG16I:
|
||||
case LOCAL_GL_RGB16I:
|
||||
case LOCAL_GL_RGBA16I:
|
||||
|
||||
case LOCAL_GL_R32I:
|
||||
case LOCAL_GL_RG32I:
|
||||
case LOCAL_GL_RGB32I:
|
||||
case LOCAL_GL_RGBA32I:
|
||||
return LOCAL_GL_INT;
|
||||
|
||||
// Unsigned int
|
||||
case LOCAL_GL_R8UI:
|
||||
case LOCAL_GL_RG8UI:
|
||||
case LOCAL_GL_RGB8UI:
|
||||
case LOCAL_GL_RGBA8UI:
|
||||
|
||||
case LOCAL_GL_R16UI:
|
||||
case LOCAL_GL_RG16UI:
|
||||
case LOCAL_GL_RGB16UI:
|
||||
case LOCAL_GL_RGBA16UI:
|
||||
|
||||
case LOCAL_GL_R32UI:
|
||||
case LOCAL_GL_RG32UI:
|
||||
case LOCAL_GL_RGB32UI:
|
||||
case LOCAL_GL_RGBA32UI:
|
||||
|
||||
case LOCAL_GL_RGB10_A2UI:
|
||||
return LOCAL_GL_UNSIGNED_INT;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad `internalFormat`.");
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Framebuffer objects
|
||||
|
||||
static bool
|
||||
GetFBInfoForBlit(const WebGLFramebuffer* fb, WebGLContext* webgl,
|
||||
const char* const fbInfo, GLsizei* const out_samples,
|
||||
const webgl::FormatInfo** const out_colorFormat,
|
||||
const webgl::FormatInfo** const out_depthFormat,
|
||||
const webgl::FormatInfo** const out_stencilFormat)
|
||||
GLenum* const out_colorFormat, GLenum* const out_depthFormat,
|
||||
GLenum* const out_stencilFormat)
|
||||
{
|
||||
auto status = fb->PrecheckFramebufferStatus();
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
@ -28,58 +123,36 @@ GetFBInfoForBlit(const WebGLFramebuffer* fb, WebGLContext* webgl,
|
||||
}
|
||||
|
||||
*out_samples = 1; // TODO
|
||||
*out_colorFormat = nullptr;
|
||||
*out_depthFormat = nullptr;
|
||||
*out_stencilFormat = nullptr;
|
||||
|
||||
if (fb->ColorAttachment(0).IsDefined()) {
|
||||
const auto& attachment = fb->ColorAttachment(0);
|
||||
*out_colorFormat = attachment.Format()->format;
|
||||
const auto& attachement = fb->ColorAttachment(0);
|
||||
*out_colorFormat = attachement.EffectiveInternalFormat().get();
|
||||
} else {
|
||||
*out_colorFormat = 0;
|
||||
}
|
||||
|
||||
if (fb->DepthStencilAttachment().IsDefined()) {
|
||||
const auto& attachment = fb->DepthStencilAttachment();
|
||||
*out_depthFormat = attachment.Format()->format;
|
||||
const auto& attachement = fb->DepthStencilAttachment();
|
||||
*out_depthFormat = attachement.EffectiveInternalFormat().get();
|
||||
*out_stencilFormat = *out_depthFormat;
|
||||
} else {
|
||||
if (fb->DepthAttachment().IsDefined()) {
|
||||
const auto& attachment = fb->DepthAttachment();
|
||||
*out_depthFormat = attachment.Format()->format;
|
||||
const auto& attachement = fb->DepthAttachment();
|
||||
*out_depthFormat = attachement.EffectiveInternalFormat().get();
|
||||
} else {
|
||||
*out_depthFormat = 0;
|
||||
}
|
||||
|
||||
if (fb->StencilAttachment().IsDefined()) {
|
||||
const auto& attachment = fb->StencilAttachment();
|
||||
*out_stencilFormat = attachment.Format()->format;
|
||||
const auto& attachement = fb->StencilAttachment();
|
||||
*out_stencilFormat = attachement.EffectiveInternalFormat().get();
|
||||
} else {
|
||||
*out_stencilFormat = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
GetBackbufferFormats(const WebGLContextOptions& options,
|
||||
const webgl::FormatInfo** const out_color,
|
||||
const webgl::FormatInfo** const out_depth,
|
||||
const webgl::FormatInfo** const out_stencil)
|
||||
{
|
||||
const auto effFormat = options.alpha ? webgl::EffectiveFormat::RGBA8
|
||||
: webgl::EffectiveFormat::RGB8;
|
||||
*out_color = webgl::GetFormat(effFormat);
|
||||
|
||||
*out_depth = nullptr;
|
||||
*out_stencil = nullptr;
|
||||
if (options.depth && options.stencil) {
|
||||
*out_depth = webgl::GetFormat(webgl::EffectiveFormat::DEPTH24_STENCIL8);
|
||||
*out_stencil = *out_depth;
|
||||
} else {
|
||||
if (options.depth) {
|
||||
*out_depth = webgl::GetFormat(webgl::EffectiveFormat::DEPTH_COMPONENT16);
|
||||
}
|
||||
if (options.stencil) {
|
||||
*out_stencil = webgl::GetFormat(webgl::EffectiveFormat::STENCIL_INDEX8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
@ -123,9 +196,9 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
|
||||
}
|
||||
|
||||
GLsizei srcSamples;
|
||||
const webgl::FormatInfo* srcColorFormat = nullptr;
|
||||
const webgl::FormatInfo* srcDepthFormat = nullptr;
|
||||
const webgl::FormatInfo* srcStencilFormat = nullptr;
|
||||
GLenum srcColorFormat = 0;
|
||||
GLenum srcDepthFormat = 0;
|
||||
GLenum srcStencilFormat = 0;
|
||||
|
||||
if (mBoundReadFramebuffer) {
|
||||
if (!GetFBInfoForBlit(mBoundReadFramebuffer, this, "READ_FRAMEBUFFER",
|
||||
@ -137,14 +210,26 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
|
||||
} else {
|
||||
srcSamples = 1; // Always 1.
|
||||
|
||||
GetBackbufferFormats(mOptions, &srcColorFormat, &srcDepthFormat,
|
||||
&srcStencilFormat);
|
||||
// TODO: Don't hardcode these.
|
||||
srcColorFormat = mOptions.alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
|
||||
|
||||
if (mOptions.depth && mOptions.stencil) {
|
||||
srcDepthFormat = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
srcStencilFormat = srcDepthFormat;
|
||||
} else {
|
||||
if (mOptions.depth) {
|
||||
srcDepthFormat = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
if (mOptions.stencil) {
|
||||
srcStencilFormat = LOCAL_GL_STENCIL_INDEX8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLsizei dstSamples;
|
||||
const webgl::FormatInfo* dstColorFormat = nullptr;
|
||||
const webgl::FormatInfo* dstDepthFormat = nullptr;
|
||||
const webgl::FormatInfo* dstStencilFormat = nullptr;
|
||||
GLenum dstColorFormat = 0;
|
||||
GLenum dstDepthFormat = 0;
|
||||
GLenum dstStencilFormat = 0;
|
||||
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (!GetFBInfoForBlit(mBoundDrawFramebuffer, this, "DRAW_FRAMEBUFFER",
|
||||
@ -156,39 +241,36 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
|
||||
} else {
|
||||
dstSamples = gl->Screen()->Samples();
|
||||
|
||||
GetBackbufferFormats(mOptions, &dstColorFormat, &dstDepthFormat,
|
||||
&dstStencilFormat);
|
||||
// TODO: Don't hardcode these.
|
||||
dstColorFormat = mOptions.alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
|
||||
|
||||
if (mOptions.depth && mOptions.stencil) {
|
||||
dstDepthFormat = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
dstStencilFormat = dstDepthFormat;
|
||||
} else {
|
||||
if (mOptions.depth) {
|
||||
dstDepthFormat = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
if (mOptions.stencil) {
|
||||
dstStencilFormat = LOCAL_GL_STENCIL_INDEX8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
|
||||
const auto fnSignlessType = [](const webgl::FormatInfo* format)
|
||||
-> webgl::ComponentType
|
||||
{
|
||||
if (!format)
|
||||
return webgl::ComponentType::None;
|
||||
|
||||
switch (format->componentType) {
|
||||
case webgl::ComponentType::UInt:
|
||||
return webgl::ComponentType::Int;
|
||||
|
||||
case webgl::ComponentType::NormUInt:
|
||||
return webgl::ComponentType::NormInt;
|
||||
|
||||
default:
|
||||
return format->componentType;
|
||||
}
|
||||
};
|
||||
|
||||
const auto srcType = fnSignlessType(srcColorFormat);
|
||||
const auto dstType = fnSignlessType(dstColorFormat);
|
||||
|
||||
if (srcType != dstType) {
|
||||
ErrorInvalidOperation("blitFramebuffer: Color buffer format component type"
|
||||
const GLenum srcColorType = srcColorFormat ? ValueTypeForFormat(srcColorFormat)
|
||||
: 0;
|
||||
const GLenum dstColorType = dstColorFormat ? ValueTypeForFormat(dstColorFormat)
|
||||
: 0;
|
||||
if (dstColorType != srcColorType) {
|
||||
ErrorInvalidOperation("blitFramebuffer: Color buffer value type"
|
||||
" mismatch.");
|
||||
return;
|
||||
}
|
||||
|
||||
const bool srcIsInt = (srcType == webgl::ComponentType::Int);
|
||||
const bool srcIsInt = srcColorType == LOCAL_GL_INT ||
|
||||
srcColorType == LOCAL_GL_UNSIGNED_INT;
|
||||
if (srcIsInt && filter != LOCAL_GL_NEAREST) {
|
||||
ErrorInvalidOperation("blitFramebuffer: Integer read buffers can only"
|
||||
" be filtered with NEAREST.");
|
||||
@ -296,16 +378,16 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be >= 0.");
|
||||
|
||||
switch (texture->Target().get()) {
|
||||
switch (texture->Target()) {
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
if (uint32_t(layer) >= mImplMax3DTextureSize) {
|
||||
if ((GLuint) layer >= mGLMax3DTextureSize) {
|
||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
|
||||
"MAX_3D_TEXTURE_SIZE");
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
if (uint32_t(layer) >= mImplMaxArrayTextureLayers) {
|
||||
if ((GLuint) layer >= mGLMaxArrayTextureLayers) {
|
||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
|
||||
"MAX_ARRAY_TEXTURE_LAYERS");
|
||||
}
|
||||
@ -315,6 +397,9 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
|
||||
return ErrorInvalidOperation("framebufferTextureLayer: texture must be an "
|
||||
"existing 3D texture, or a 2D texture array.");
|
||||
}
|
||||
} else {
|
||||
return ErrorInvalidOperation("framebufferTextureLayer: texture must be an "
|
||||
"existing 3D texture, or a 2D texture array.");
|
||||
}
|
||||
|
||||
WebGLFramebuffer* fb;
|
||||
@ -345,10 +430,96 @@ WebGL2Context::GetFramebufferAttachmentParameter(JSContext* cx,
|
||||
GLenum target,
|
||||
GLenum attachment,
|
||||
GLenum pname,
|
||||
ErrorResult& out_error)
|
||||
ErrorResult& rv)
|
||||
{
|
||||
return WebGLContext::GetFramebufferAttachmentParameter(cx, target, attachment, pname,
|
||||
out_error);
|
||||
if (IsContextLost())
|
||||
return JS::NullValue();
|
||||
|
||||
// OpenGL ES 3.0.4 (August 27, 2014) 6.1. QUERYING GL STATE 240
|
||||
// "getFramebufferAttachmentParamter returns information about attachments of a bound
|
||||
// framebuffer object. target must be DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or
|
||||
// FRAMEBUFFER."
|
||||
|
||||
if (!ValidateFramebufferTarget(target, "getFramebufferAttachmentParameter"))
|
||||
return JS::NullValue();
|
||||
|
||||
// FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER.
|
||||
if (target == LOCAL_GL_FRAMEBUFFER)
|
||||
target = LOCAL_GL_DRAW_FRAMEBUFFER;
|
||||
|
||||
WebGLFramebuffer* boundFB = nullptr;
|
||||
switch (target) {
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER: boundFB = mBoundDrawFramebuffer; break;
|
||||
case LOCAL_GL_READ_FRAMEBUFFER: boundFB = mBoundReadFramebuffer; break;
|
||||
}
|
||||
|
||||
if (boundFB) {
|
||||
return boundFB->GetAttachmentParameter(cx, attachment, pname, rv);
|
||||
}
|
||||
|
||||
// Handle default FB
|
||||
const gl::GLFormats& formats = gl->GetGLFormats();
|
||||
GLenum internalFormat = LOCAL_GL_NONE;
|
||||
|
||||
/* If the default framebuffer is bound to target, then attachment must be BACK,
|
||||
identifying the color buffer; DEPTH, identifying the depth buffer; or STENCIL,
|
||||
identifying the stencil buffer. */
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_BACK:
|
||||
internalFormat = formats.color_texInternalFormat;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_DEPTH:
|
||||
internalFormat = formats.depth;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_STENCIL:
|
||||
internalFormat = formats.stencil;
|
||||
break;
|
||||
|
||||
default:
|
||||
ErrorInvalidEnum("getFramebufferAttachmentParameter: Can only query "
|
||||
"attachment BACK, DEPTH, or STENCIL from default "
|
||||
"framebuffer");
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
const FormatInfo* info = webgl::GetInfoBySizedFormat(internalFormat);
|
||||
MOZ_RELEASE_ASSERT(info);
|
||||
EffectiveFormat effectiveFormat = info->effectiveFormat;
|
||||
|
||||
switch (pname) {
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
|
||||
return JS::Int32Value(LOCAL_GL_FRAMEBUFFER_DEFAULT);
|
||||
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
|
||||
return JS::Int32Value(webgl::GetComponentSize(effectiveFormat, pname));
|
||||
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
|
||||
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT &&
|
||||
pname == LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)
|
||||
{
|
||||
ErrorInvalidOperation("getFramebufferAttachmentParameter: Querying "
|
||||
"FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE against "
|
||||
"DEPTH_STENCIL_ATTACHMENT is an error.");
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
return JS::Int32Value(webgl::GetComponentType(effectiveFormat));
|
||||
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
|
||||
return JS::Int32Value(webgl::GetColorEncoding(effectiveFormat));
|
||||
}
|
||||
|
||||
/* Any combinations of framebuffer type and pname not described above will generate an
|
||||
INVALID_ENUM error. */
|
||||
ErrorInvalidEnum("getFramebufferAttachmentParameter: Invalid combination of ");
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
// Map attachments intended for the default buffer, to attachments for a non-
|
||||
@ -386,14 +557,12 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
|
||||
const dom::Sequence<GLenum>& attachments,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
const char funcName[] = "invalidateSubFramebuffer";
|
||||
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
|
||||
return;
|
||||
|
||||
const WebGLFramebuffer* fb;
|
||||
@ -414,10 +583,9 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
|
||||
MOZ_CRASH("Bad target.");
|
||||
}
|
||||
|
||||
const bool badColorAttachmentIsInvalidOp = true;
|
||||
for (size_t i = 0; i < attachments.Length(); i++) {
|
||||
if (!ValidateFramebufferAttachment(fb, attachments[i], funcName,
|
||||
badColorAttachmentIsInvalidOp))
|
||||
if (!ValidateFramebufferAttachment(fb, attachments[i],
|
||||
"invalidateFramebuffer"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -426,7 +594,8 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
|
||||
// InvalidateFramebuffer is a hint to the driver. Should be OK to
|
||||
// skip calls if not supported, for example by OSX 10.9 GL
|
||||
// drivers.
|
||||
if (!gl->IsSupported(gl::GLFeature::invalidate_framebuffer))
|
||||
static bool invalidateFBSupported = gl->IsSupported(gl::GLFeature::invalidate_framebuffer);
|
||||
if (!invalidateFBSupported)
|
||||
return;
|
||||
|
||||
if (!fb && !isDefaultFB) {
|
||||
@ -436,8 +605,7 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
|
||||
return;
|
||||
}
|
||||
|
||||
gl->fInvalidateFramebuffer(target, tmpAttachments.Length(),
|
||||
tmpAttachments.Elements());
|
||||
gl->fInvalidateFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements());
|
||||
} else {
|
||||
gl->fInvalidateFramebuffer(target, attachments.Length(), attachments.Elements());
|
||||
}
|
||||
@ -448,21 +616,14 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
const char funcName[] = "invalidateSubFramebuffer";
|
||||
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
|
||||
return;
|
||||
|
||||
if (width < 0 || height < 0) {
|
||||
ErrorInvalidValue("%s: width and height must be >= 0.", funcName);
|
||||
return;
|
||||
}
|
||||
|
||||
const WebGLFramebuffer* fb;
|
||||
bool isDefaultFB;
|
||||
switch (target) {
|
||||
@ -481,10 +642,9 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
|
||||
MOZ_CRASH("Bad target.");
|
||||
}
|
||||
|
||||
const bool badColorAttachmentIsInvalidOp = true;
|
||||
for (size_t i = 0; i < attachments.Length(); i++) {
|
||||
if (!ValidateFramebufferAttachment(fb, attachments[i], funcName,
|
||||
badColorAttachmentIsInvalidOp))
|
||||
if (!ValidateFramebufferAttachment(fb, attachments[i],
|
||||
"invalidateSubFramebuffer"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -493,7 +653,8 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
|
||||
// InvalidateFramebuffer is a hint to the driver. Should be OK to
|
||||
// skip calls if not supported, for example by OSX 10.9 GL
|
||||
// drivers.
|
||||
if (!gl->IsSupported(gl::GLFeature::invalidate_framebuffer))
|
||||
static bool invalidateFBSupported = gl->IsSupported(gl::GLFeature::invalidate_framebuffer);
|
||||
if (!invalidateFBSupported)
|
||||
return;
|
||||
|
||||
if (!fb && !isDefaultFB) {
|
||||
@ -503,11 +664,11 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
|
||||
return;
|
||||
}
|
||||
|
||||
gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(),
|
||||
tmpAttachments.Elements(), x, y, width, height);
|
||||
gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements(),
|
||||
x, y, width, height);
|
||||
} else {
|
||||
gl->fInvalidateSubFramebuffer(target, attachments.Length(),
|
||||
attachments.Elements(), x, y, width, height);
|
||||
gl->fInvalidateSubFramebuffer(target, attachments.Length(), attachments.Elements(),
|
||||
x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,7 +679,7 @@ WebGL2Context::ReadBuffer(GLenum mode)
|
||||
return;
|
||||
|
||||
const bool isColorAttachment = (mode >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mode <= LastColorAttachmentEnum());
|
||||
mode <= LastColorAttachment());
|
||||
|
||||
if (mode != LOCAL_GL_NONE && mode != LOCAL_GL_BACK && !isColorAttachment) {
|
||||
ErrorInvalidEnum("readBuffer: `mode` must be one of NONE, BACK, or "
|
||||
|
@ -59,6 +59,8 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
/* fall through */
|
||||
|
||||
/* GLint */
|
||||
case LOCAL_GL_MAX_3D_TEXTURE_SIZE:
|
||||
case LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS:
|
||||
case LOCAL_GL_MAX_COMBINED_UNIFORM_BLOCKS:
|
||||
case LOCAL_GL_MAX_ELEMENTS_INDICES:
|
||||
case LOCAL_GL_MAX_ELEMENTS_VERTICES:
|
||||
@ -87,12 +89,6 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
return JS::Int32Value(val);
|
||||
}
|
||||
|
||||
case LOCAL_GL_MAX_3D_TEXTURE_SIZE:
|
||||
return JS::Int32Value(mImplMax3DTextureSize);
|
||||
|
||||
case LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS:
|
||||
return JS::Int32Value(mImplMaxArrayTextureLayers);
|
||||
|
||||
case LOCAL_GL_MAX_VARYING_COMPONENTS: {
|
||||
// On OS X Core Profile this is buggy. The spec says that the
|
||||
// value is 4 * GL_MAX_VARYING_VECTORS
|
||||
@ -155,7 +151,9 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
return WebGLObjectAsJSValue(cx, mBoundSamplers[mActiveTexture].get(), rv);
|
||||
|
||||
case LOCAL_GL_TEXTURE_BINDING_2D_ARRAY:
|
||||
return WebGLObjectAsJSValue(cx, mBound2DArrayTextures[mActiveTexture].get(), rv);
|
||||
// TODO: Implement gl.TEXTURE_2D_ARRAY
|
||||
// return WebGLObjectAsJSValue(cx, mBound2DTextureArrays[mActiveTexture].get(), rv);
|
||||
return JS::NullValue();
|
||||
|
||||
case LOCAL_GL_TEXTURE_BINDING_3D:
|
||||
return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);
|
||||
|
@ -11,19 +11,15 @@
|
||||
namespace mozilla {
|
||||
|
||||
void
|
||||
WebGL2Context::TexStorage2D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height)
|
||||
WebGL2Context::TexStorage2D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height)
|
||||
{
|
||||
const char funcName[] = "TexStorage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexTarget target;
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &target, &tex))
|
||||
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
|
||||
return;
|
||||
|
||||
const GLsizei depth = 1;
|
||||
tex->TexStorage(funcName, target, levels, internalFormat, width, height, depth);
|
||||
tex->TexStorage2D(texTarget, levels, internalFormat, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
@ -31,178 +27,88 @@ WebGL2Context::TexStorage3D(GLenum rawTexTarget, GLsizei levels, GLenum internal
|
||||
GLsizei width, GLsizei height, GLsizei depth)
|
||||
{
|
||||
const char funcName[] = "texStorage3D";
|
||||
const uint8_t funcDims = 3;
|
||||
|
||||
TexTarget target;
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &target, &tex))
|
||||
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
|
||||
return;
|
||||
|
||||
tex->TexStorage(funcName, target, levels, internalFormat, width, height, depth);
|
||||
tex->TexStorage3D(texTarget, levels, internalFormat, width, height, depth);
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth, GLint border,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView)
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
const char funcName[] = "texImage3D";
|
||||
const uint8_t funcDims = 3;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = false;
|
||||
const GLint xOffset = 0;
|
||||
const GLint yOffset = 0;
|
||||
const GLint zOffset = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, width, height, depth, border, unpackFormat,
|
||||
unpackType, maybeView);
|
||||
tex->TexImage3D(texImageTarget, level, internalFormat, width, height, depth, border,
|
||||
unpackFormat, unpackType, maybeView, &out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLenum unpackFormat, GLenum unpackType,
|
||||
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult& /*out_rv*/)
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
const char funcName[] = "texSubImage3D";
|
||||
const uint8_t funcDims = 3;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = true;
|
||||
const GLenum internalFormat = 0;
|
||||
const GLint border = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, width, height, depth, border, unpackFormat,
|
||||
unpackType, maybeView);
|
||||
tex->TexSubImage3D(texImageTarget, level, xOffset, yOffset, zOffset, width, height,
|
||||
depth, unpackFormat, unpackType, maybeView, &out_rv);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult& /*out_rv*/)
|
||||
WebGL2Context::TexSubImage3D(GLenum target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
const char funcName[] = "texSubImage3D";
|
||||
const uint8_t funcDims = 3;
|
||||
|
||||
TexImageTarget target;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = true;
|
||||
const GLenum internalFormat = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, unpackFormat, unpackType, imageData);
|
||||
GenerateWarning("texSubImage3D: Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_rv)
|
||||
WebGL2Context::CopyTexSubImage3D(GLenum target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height)
|
||||
{
|
||||
const char funcName[] = "texSubImage3D";
|
||||
const uint8_t funcDims = 3;
|
||||
|
||||
TexImageTarget target;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = true;
|
||||
const GLenum internalFormat = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, unpackFormat, unpackType, elem, out_rv);
|
||||
GenerateWarning("copyTexSubImage3D: Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::CompressedTexImage3D(GLenum rawTexImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
|
||||
WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
|
||||
{
|
||||
const char funcName[] = "compressedTexImage3D";
|
||||
const uint8_t funcDims = 3;
|
||||
|
||||
TexImageTarget target;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CompressedTexImage(funcName, target, level, internalFormat, width, height, depth,
|
||||
border, view);
|
||||
GenerateWarning("compressedTexImage3D: Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::CompressedTexSubImage3D(GLenum rawTexImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum sizedUnpackFormat,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
|
||||
GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
|
||||
{
|
||||
const char funcName[] = "compressedTexSubImage3D";
|
||||
const uint8_t funcDims = 3;
|
||||
|
||||
TexImageTarget target;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CompressedTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width,
|
||||
height, depth, sizedUnpackFormat, view);
|
||||
GenerateWarning("compressedTexSubImage3D: Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::CopyTexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height)
|
||||
{
|
||||
const char funcName[] = "copyTexSubImage3D";
|
||||
const uint8_t funcDims = 3;
|
||||
|
||||
TexImageTarget target;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CopyTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, x, y, width,
|
||||
height);
|
||||
}
|
||||
|
||||
/*virtual*/ bool
|
||||
bool
|
||||
WebGL2Context::IsTexParamValid(GLenum pname) const
|
||||
{
|
||||
switch (pname) {
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
bool IsElementArrayUsedWithMultipleTypes() const;
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
|
||||
|
@ -95,10 +95,6 @@ WebGLContextOptions::WebGLContextOptions()
|
||||
alpha = false;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ const uint32_t WebGLContext::kMinMaxColorAttachments = 4;
|
||||
/*static*/ const uint32_t WebGLContext::kMinMaxDrawBuffers = 4;
|
||||
|
||||
WebGLContext::WebGLContext()
|
||||
: WebGLContextUnchecked(nullptr)
|
||||
, mBypassShaderValidation(false)
|
||||
@ -115,6 +111,11 @@ WebGLContext::WebGLContext()
|
||||
mOptionsFrozen = false;
|
||||
|
||||
mActiveTexture = 0;
|
||||
mPixelStoreFlipY = false;
|
||||
mPixelStorePremultiplyAlpha = false;
|
||||
mPixelStoreColorspaceConversion = BROWSER_DEFAULT_WEBGL;
|
||||
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
|
||||
|
||||
mVertexAttrib0Vector[0] = 0;
|
||||
mVertexAttrib0Vector[1] = 0;
|
||||
@ -139,6 +140,31 @@ WebGLContext::WebGLContext()
|
||||
mDepthTestEnabled = 0;
|
||||
mStencilTestEnabled = 0;
|
||||
|
||||
// initialize some GL values: we're going to get them from the GL and use them as the sizes of arrays,
|
||||
// so in case glGetIntegerv leaves them uninitialized because of a GL bug, we would have very weird crashes.
|
||||
mGLMaxVertexAttribs = 0;
|
||||
mGLMaxTextureUnits = 0;
|
||||
mGLMaxTextureSize = 0;
|
||||
mGLMaxTextureSizeLog2 = 0;
|
||||
mGLMaxCubeMapTextureSize = 0;
|
||||
mGLMaxCubeMapTextureSizeLog2 = 0;
|
||||
mGLMaxRenderbufferSize = 0;
|
||||
mGLMaxTextureImageUnits = 0;
|
||||
mGLMaxVertexTextureImageUnits = 0;
|
||||
mGLMaxVaryingVectors = 0;
|
||||
mGLMaxFragmentUniformVectors = 0;
|
||||
mGLMaxVertexUniformVectors = 0;
|
||||
mGLMaxColorAttachments = 1;
|
||||
mGLMaxDrawBuffers = 1;
|
||||
mGLMaxTransformFeedbackSeparateAttribs = 0;
|
||||
mGLMaxUniformBufferBindings = 0;
|
||||
mGLMax3DTextureSize = 0;
|
||||
mGLMaxArrayTextureLayers = 0;
|
||||
|
||||
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
|
||||
mPixelStorePackAlignment = 4;
|
||||
mPixelStoreUnpackAlignment = 4;
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
// XXX mtseng: bug 709490, not thread safe
|
||||
WebGLMemoryTracker::AddWebGLContext(this);
|
||||
@ -198,7 +224,6 @@ WebGLContext::DestroyResourcesAndContext()
|
||||
mBound2DTextures.Clear();
|
||||
mBoundCubeMapTextures.Clear();
|
||||
mBound3DTextures.Clear();
|
||||
mBound2DArrayTextures.Clear();
|
||||
mBoundSamplers.Clear();
|
||||
mBoundArrayBuffer = nullptr;
|
||||
mBoundCopyReadBuffer = nullptr;
|
||||
@ -242,14 +267,10 @@ WebGLContext::DestroyResourcesAndContext()
|
||||
while (!mTransformFeedbacks.isEmpty())
|
||||
mTransformFeedbacks.getLast()->DeleteOnce();
|
||||
|
||||
mFakeBlack_2D_0000 = nullptr;
|
||||
mFakeBlack_2D_0001 = nullptr;
|
||||
mFakeBlack_CubeMap_0000 = nullptr;
|
||||
mFakeBlack_CubeMap_0001 = nullptr;
|
||||
mFakeBlack_3D_0000 = nullptr;
|
||||
mFakeBlack_3D_0001 = nullptr;
|
||||
mFakeBlack_2D_Array_0000 = nullptr;
|
||||
mFakeBlack_2D_Array_0001 = nullptr;
|
||||
mBlackOpaqueTexture2D = nullptr;
|
||||
mBlackOpaqueTextureCubeMap = nullptr;
|
||||
mBlackTransparentTexture2D = nullptr;
|
||||
mBlackTransparentTextureCubeMap = nullptr;
|
||||
|
||||
if (mFakeVertexAttrib0BufferObject)
|
||||
gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
|
||||
@ -1277,37 +1298,37 @@ WebGLContext::MozGetUnderlyingParamString(uint32_t pname, nsAString& retval)
|
||||
void
|
||||
WebGLContext::ClearScreen()
|
||||
{
|
||||
bool colorAttachmentsMask[WebGLContext::kMaxColorAttachments] = {false};
|
||||
|
||||
MakeContextCurrent();
|
||||
ScopedBindFramebuffer autoFB(gl, 0);
|
||||
|
||||
const bool changeDrawBuffers = (mDefaultFB_DrawBuffer0 != LOCAL_GL_BACK);
|
||||
if (changeDrawBuffers) {
|
||||
const GLenum back = LOCAL_GL_BACK;
|
||||
gl->fDrawBuffers(1, &back);
|
||||
}
|
||||
|
||||
GLbitfield bufferBits = LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
GLbitfield clearMask = LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
if (mOptions.depth)
|
||||
bufferBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
||||
clearMask |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
||||
if (mOptions.stencil)
|
||||
bufferBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
clearMask |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
|
||||
ForceClearFramebufferWithDefaultValues(bufferBits, mNeedsFakeNoAlpha);
|
||||
colorAttachmentsMask[0] = true;
|
||||
|
||||
if (changeDrawBuffers) {
|
||||
gl->fDrawBuffers(1, &mDefaultFB_DrawBuffer0);
|
||||
}
|
||||
ForceClearFramebufferWithDefaultValues(mNeedsFakeNoAlpha, clearMask,
|
||||
colorAttachmentsMask);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
|
||||
bool fakeNoAlpha)
|
||||
WebGLContext::ForceClearFramebufferWithDefaultValues(bool fakeNoAlpha, GLbitfield mask,
|
||||
const bool colorAttachmentsMask[kMaxColorAttachments])
|
||||
{
|
||||
MakeContextCurrent();
|
||||
|
||||
const bool initializeColorBuffer = bool(clearBits & LOCAL_GL_COLOR_BUFFER_BIT);
|
||||
const bool initializeDepthBuffer = bool(clearBits & LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
const bool initializeStencilBuffer = bool(clearBits & LOCAL_GL_STENCIL_BUFFER_BIT);
|
||||
bool initializeColorBuffer = 0 != (mask & LOCAL_GL_COLOR_BUFFER_BIT);
|
||||
bool initializeDepthBuffer = 0 != (mask & LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
bool initializeStencilBuffer = 0 != (mask & LOCAL_GL_STENCIL_BUFFER_BIT);
|
||||
bool drawBuffersIsEnabled = IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers);
|
||||
bool shouldOverrideDrawBuffers = false;
|
||||
bool usingDefaultFrameBuffer = !mBoundDrawFramebuffer;
|
||||
|
||||
GLenum currentDrawBuffers[WebGLContext::kMaxColorAttachments];
|
||||
|
||||
// Fun GL fact: No need to worry about the viewport here, glViewport is just
|
||||
// setting up a coordinates transformation, it doesn't affect glClear at all.
|
||||
@ -1318,6 +1339,38 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
|
||||
gl->fDisable(LOCAL_GL_SCISSOR_TEST);
|
||||
|
||||
if (initializeColorBuffer) {
|
||||
|
||||
if (drawBuffersIsEnabled) {
|
||||
|
||||
GLenum drawBuffersCommand[WebGLContext::kMaxColorAttachments] = { LOCAL_GL_NONE };
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxDrawBuffers; i++) {
|
||||
GLint temp;
|
||||
gl->fGetIntegerv(LOCAL_GL_DRAW_BUFFER0 + i, &temp);
|
||||
currentDrawBuffers[i] = temp;
|
||||
|
||||
if (colorAttachmentsMask[i]) {
|
||||
drawBuffersCommand[i] = LOCAL_GL_COLOR_ATTACHMENT0 + i;
|
||||
}
|
||||
if (currentDrawBuffers[i] != drawBuffersCommand[i])
|
||||
shouldOverrideDrawBuffers = true;
|
||||
}
|
||||
|
||||
// When clearing the default framebuffer, we must be clearing only
|
||||
// GL_BACK, and nothing else, or else gl may return an error. We will
|
||||
// only use the first element of currentDrawBuffers in this case.
|
||||
if (usingDefaultFrameBuffer) {
|
||||
gl->Screen()->SetDrawBuffer(LOCAL_GL_BACK);
|
||||
if (currentDrawBuffers[0] == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
currentDrawBuffers[0] = LOCAL_GL_BACK;
|
||||
shouldOverrideDrawBuffers = false;
|
||||
}
|
||||
// calling draw buffers can cause resolves on adreno drivers so
|
||||
// we try to avoid calling it
|
||||
if (shouldOverrideDrawBuffers)
|
||||
gl->fDrawBuffers(mGLMaxDrawBuffers, drawBuffersCommand);
|
||||
}
|
||||
|
||||
gl->fColorMask(1, 1, 1, 1);
|
||||
|
||||
if (fakeNoAlpha) {
|
||||
@ -1345,7 +1398,7 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
|
||||
}
|
||||
|
||||
// Do the clear!
|
||||
gl->fClear(clearBits);
|
||||
gl->fClear(mask);
|
||||
|
||||
// And reset!
|
||||
if (mScissorTestEnabled)
|
||||
@ -1357,6 +1410,15 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
|
||||
|
||||
// Restore GL state after clearing.
|
||||
if (initializeColorBuffer) {
|
||||
|
||||
if (drawBuffersIsEnabled) {
|
||||
if (usingDefaultFrameBuffer) {
|
||||
gl->Screen()->SetDrawBuffer(currentDrawBuffers[0]);
|
||||
} else if (shouldOverrideDrawBuffers) {
|
||||
gl->fDrawBuffers(mGLMaxDrawBuffers, currentDrawBuffers);
|
||||
}
|
||||
}
|
||||
|
||||
gl->fColorMask(mColorWriteMask[0],
|
||||
mColorWriteMask[1],
|
||||
mColorWriteMask[2],
|
||||
@ -1756,30 +1818,17 @@ WebGLContext::DidRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::ValidateCurFBForRead(const char* funcName,
|
||||
const webgl::FormatUsageInfo** const out_format,
|
||||
uint32_t* const out_width, uint32_t* const out_height)
|
||||
size_t
|
||||
RoundUpToMultipleOf(size_t value, size_t multiple)
|
||||
{
|
||||
if (!mBoundReadFramebuffer) {
|
||||
ClearBackbufferIfNeeded();
|
||||
size_t overshoot = value + multiple - 1;
|
||||
return overshoot - (overshoot % multiple);
|
||||
}
|
||||
|
||||
// FIXME - here we're assuming that the default framebuffer is backed by
|
||||
// UNSIGNED_BYTE that might not always be true, say if we had a 16bpp default
|
||||
// framebuffer.
|
||||
auto effFormat = mOptions.alpha ? webgl::EffectiveFormat::RGBA8
|
||||
: webgl::EffectiveFormat::RGB8;
|
||||
|
||||
*out_format = mFormatUsage->GetUsage(effFormat);
|
||||
MOZ_ASSERT(*out_format);
|
||||
|
||||
*out_width = mWidth;
|
||||
*out_height = mHeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
return mBoundReadFramebuffer->ValidateForRead(funcName, out_format, out_width,
|
||||
out_height);
|
||||
CheckedUint32
|
||||
RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y)
|
||||
{
|
||||
return ((x + y - 1) / y) * y;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1820,215 +1869,6 @@ WebGLContext::ScopedMaskWorkaround::~ScopedMaskWorkaround()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
ScopedUnpackReset::ScopedUnpackReset(WebGLContext* webgl)
|
||||
: ScopedGLWrapper<ScopedUnpackReset>(webgl->gl)
|
||||
, mWebGL(webgl)
|
||||
{
|
||||
if (mWebGL->mPixelStore_UnpackAlignment != 4) mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
if (mWebGL->IsWebGL2()) {
|
||||
if (mWebGL->mPixelStore_UnpackRowLength != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH , 0);
|
||||
if (mWebGL->mPixelStore_UnpackImageHeight != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, 0);
|
||||
if (mWebGL->mPixelStore_UnpackSkipPixels != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS , 0);
|
||||
if (mWebGL->mPixelStore_UnpackSkipRows != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS , 0);
|
||||
if (mWebGL->mPixelStore_UnpackSkipImages != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES , 0);
|
||||
|
||||
if (mWebGL->mBoundPixelUnpackBuffer) mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScopedUnpackReset::UnwrapImpl()
|
||||
{
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mWebGL->mPixelStore_UnpackAlignment);
|
||||
|
||||
if (mWebGL->IsWebGL2()) {
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH , mWebGL->mPixelStore_UnpackRowLength );
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mWebGL->mPixelStore_UnpackImageHeight);
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS , mWebGL->mPixelStore_UnpackSkipPixels );
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS , mWebGL->mPixelStore_UnpackSkipRows );
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES , mWebGL->mPixelStore_UnpackSkipImages );
|
||||
|
||||
GLuint pbo = 0;
|
||||
if (mWebGL->mBoundPixelUnpackBuffer) {
|
||||
pbo = mWebGL->mBoundPixelUnpackBuffer->mGLName;
|
||||
}
|
||||
|
||||
mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
void
|
||||
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)
|
||||
{
|
||||
// Only >0 if dstStartInSrc is >0:
|
||||
// 0 3 // src coords
|
||||
// | [========] // dst box
|
||||
// ^--^
|
||||
*out_intStartInSrc = std::max<int32_t>(0, dstStartInSrc);
|
||||
|
||||
// Only >0 if dstStartInSrc is <0:
|
||||
//-6 0 // src coords
|
||||
// [=====|==] // dst box
|
||||
// ^-----^
|
||||
*out_intStartInDst = std::max<int32_t>(0, 0 - dstStartInSrc);
|
||||
|
||||
int32_t intEndInSrc = std::min<int32_t>(srcSize, dstStartInSrc + dstSize);
|
||||
*out_intSize = std::max<int32_t>(0, intEndInSrc - *out_intStartInSrc);
|
||||
}
|
||||
|
||||
bool
|
||||
ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture,
|
||||
TexImageTarget target, uint32_t level,
|
||||
const webgl::FormatUsageInfo* usage, uint32_t xOffset, uint32_t yOffset,
|
||||
uint32_t zOffset, 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();
|
||||
|
||||
ScopedUnpackReset scopedReset(webgl);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it well.
|
||||
|
||||
auto compression = usage->format->compression;
|
||||
if (compression) {
|
||||
MOZ_RELEASE_ASSERT(!xOffset && !yOffset && !zOffset);
|
||||
MOZ_RELEASE_ASSERT(!respecifyTexture);
|
||||
|
||||
auto sizedFormat = usage->format->sizedFormat;
|
||||
MOZ_RELEASE_ASSERT(sizedFormat);
|
||||
|
||||
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;
|
||||
|
||||
GLenum error = DoCompressedTexSubImage(gl, target.get(), level, xOffset, yOffset,
|
||||
zOffset, width, height, depth, sizedFormat,
|
||||
byteCount, zeros.get());
|
||||
if (error)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto driverUnpackInfo = usage->idealUnpack;
|
||||
MOZ_RELEASE_ASSERT(driverUnpackInfo);
|
||||
|
||||
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;
|
||||
|
||||
GLenum error;
|
||||
if (respecifyTexture) {
|
||||
MOZ_RELEASE_ASSERT(!xOffset && !yOffset && !zOffset);
|
||||
error = DoTexImage(gl, target, level, driverUnpackInfo, width, height, depth,
|
||||
zeros.get());
|
||||
} else {
|
||||
error = DoTexSubImage(gl, target, level, xOffset, yOffset, zOffset, width, height,
|
||||
depth, packing, zeros.get());
|
||||
}
|
||||
if (error)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CheckedUint32
|
||||
WebGLContext::GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height,
|
||||
uint32_t depth, uint8_t bytesPerPixel)
|
||||
{
|
||||
if (!width || !height || !depth)
|
||||
return 0;
|
||||
|
||||
////////////////
|
||||
|
||||
const auto& maybeRowLength = mPixelStore_UnpackRowLength;
|
||||
const auto& maybeImageHeight = mPixelStore_UnpackImageHeight;
|
||||
|
||||
const auto usedPixelsPerRow = CheckedUint32(mPixelStore_UnpackSkipPixels) + width;
|
||||
const auto stridePixelsPerRow = (maybeRowLength ? CheckedUint32(maybeRowLength)
|
||||
: usedPixelsPerRow);
|
||||
|
||||
const auto usedRowsPerImage = CheckedUint32(mPixelStore_UnpackSkipRows) + height;
|
||||
const auto strideRowsPerImage = (maybeImageHeight ? CheckedUint32(maybeImageHeight)
|
||||
: usedRowsPerImage);
|
||||
|
||||
const uint32_t skipImages = (isFunc3D ? mPixelStore_UnpackSkipImages
|
||||
: 0);
|
||||
const CheckedUint32 usedImages = CheckedUint32(skipImages) + depth;
|
||||
|
||||
////////////////
|
||||
|
||||
CheckedUint32 strideBytesPerRow = bytesPerPixel * stridePixelsPerRow;
|
||||
strideBytesPerRow = RoundUpToMultipleOf(strideBytesPerRow,
|
||||
mPixelStore_UnpackAlignment);
|
||||
|
||||
const CheckedUint32 strideBytesPerImage = strideBytesPerRow * strideRowsPerImage;
|
||||
|
||||
////////////////
|
||||
|
||||
CheckedUint32 usedBytesPerRow = bytesPerPixel * usedPixelsPerRow;
|
||||
// Don't round this to the alignment, since alignment here is really just used for
|
||||
// establishing stride, particularly in WebGL 1, where you can't set ROW_LENGTH.
|
||||
|
||||
CheckedUint32 totalBytes = strideBytesPerImage * (usedImages - 1);
|
||||
totalBytes += strideBytesPerRow * (usedRowsPerImage - 1);
|
||||
totalBytes += usedBytesPerRow;
|
||||
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XPCOM goop
|
||||
|
||||
@ -2042,7 +1882,6 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
|
||||
mBound2DTextures,
|
||||
mBoundCubeMapTextures,
|
||||
mBound3DTextures,
|
||||
mBound2DArrayTextures,
|
||||
mBoundSamplers,
|
||||
mBoundArrayBuffer,
|
||||
mBoundCopyReadBuffer,
|
||||
|
@ -26,8 +26,6 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "SurfaceTypes.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "TexUnpackBlob.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include "ForceDiscreteGPUHelperCGL.h"
|
||||
@ -38,7 +36,6 @@
|
||||
#include "WebGLFormats.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLStrongTypes.h"
|
||||
#include "WebGLTexture.h"
|
||||
|
||||
// Generated
|
||||
#include "nsIDOMEventListener.h"
|
||||
@ -70,12 +67,6 @@ class nsIDocShell;
|
||||
#define MINVALUE_GL_MAX_RENDERBUFFER_SIZE 1024 // Different from the spec, which sets it to 1 on page 164
|
||||
#define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 8 // Page 164
|
||||
|
||||
/*
|
||||
* Minimum value constants define in 6.2 State Tables of OpenGL ES - 3.0.4
|
||||
*/
|
||||
#define MINVALUE_GL_MAX_3D_TEXTURE_SIZE 256
|
||||
#define MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS 256
|
||||
|
||||
/*
|
||||
* WebGL-only GLenums
|
||||
*/
|
||||
@ -87,9 +78,7 @@ class nsIDocShell;
|
||||
#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241
|
||||
|
||||
namespace mozilla {
|
||||
class ScopedCopyTexImageSource;
|
||||
class ScopedResolveTexturesForDraw;
|
||||
class ScopedUnpackReset;
|
||||
|
||||
class WebGLActiveInfo;
|
||||
class WebGLContextLossHandler;
|
||||
class WebGLBuffer;
|
||||
@ -122,7 +111,6 @@ class SourceSurface;
|
||||
namespace webgl {
|
||||
struct LinkedProgramInfo;
|
||||
class ShaderValidator;
|
||||
class TexUnpackBlob;
|
||||
} // namespace webgl
|
||||
|
||||
WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
|
||||
@ -212,9 +200,6 @@ class WebGLContext
|
||||
UNMASKED_RENDERER_WEBGL = 0x9246
|
||||
};
|
||||
|
||||
static const uint32_t kMinMaxColorAttachments;
|
||||
static const uint32_t kMinMaxDrawBuffers;
|
||||
|
||||
public:
|
||||
WebGLContext();
|
||||
|
||||
@ -315,8 +300,6 @@ public:
|
||||
return mBoundCubeMapTextures[mActiveTexture];
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
return mBound3DTextures[mActiveTexture];
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
return mBound2DArrayTextures[mActiveTexture];
|
||||
default:
|
||||
MOZ_CRASH("bad target");
|
||||
}
|
||||
@ -357,11 +340,18 @@ public:
|
||||
// all context resources to be lost.
|
||||
uint32_t Generation() { return mGeneration.value(); }
|
||||
|
||||
// Returns null if the current bound FB is not likely complete.
|
||||
const WebGLRectangleObject* CurValidDrawFBRectObject() const;
|
||||
const WebGLRectangleObject* CurValidReadFBRectObject() const;
|
||||
|
||||
static const size_t kMaxColorAttachments = 16;
|
||||
|
||||
// This is similar to GLContext::ClearSafely, but tries to minimize the
|
||||
// amount of work it does.
|
||||
// It only clears the buffers we specify, and can reset its state without
|
||||
// first having to query anything, as WebGL knows its state at all times.
|
||||
void ForceClearFramebufferWithDefaultValues(GLbitfield bufferBits, bool fakeNoAlpha);
|
||||
void ForceClearFramebufferWithDefaultValues(bool fakeNoAlpha, GLbitfield mask,
|
||||
const bool colorAttachmentsMask[kMaxColorAttachments]);
|
||||
|
||||
// Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'.
|
||||
void ClearScreen();
|
||||
@ -444,9 +434,8 @@ public:
|
||||
GLint level);
|
||||
|
||||
// Framebuffer validation
|
||||
bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum attachment,
|
||||
const char* funcName,
|
||||
bool badColorAttachmentIsInvalidOp = false);
|
||||
bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb,
|
||||
GLenum attachment, const char* funcName);
|
||||
|
||||
void FrontFace(GLenum mode);
|
||||
already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram* prog,
|
||||
@ -538,11 +527,6 @@ public:
|
||||
void LinkProgram(WebGLProgram* prog);
|
||||
void PixelStorei(GLenum pname, GLint param);
|
||||
void PolygonOffset(GLfloat factor, GLfloat units);
|
||||
protected:
|
||||
bool DoReadPixelsAndConvert(GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum destFormat, GLenum destType, void* destBytes,
|
||||
GLenum auxReadFormat, GLenum auxReadType);
|
||||
public:
|
||||
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
|
||||
@ -905,62 +889,46 @@ public:
|
||||
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult&);
|
||||
ErrorResult& out_rv);
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult&);
|
||||
ErrorResult& out_rv);
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_error);
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLsizei width, GLsizei height, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult&);
|
||||
ErrorResult& out_rv);
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult&);
|
||||
ErrorResult& out_rv);
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_error);
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
// Allow whatever element unpackTypes the bindings are willing to pass
|
||||
// us in Tex(Sub)Image2D
|
||||
template<typename T>
|
||||
inline void
|
||||
TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, T& elem, ErrorResult& out_error)
|
||||
template<typename ElementT>
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, ElementT& elem,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType, &elem,
|
||||
&out_error);
|
||||
&out_rv);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, T& elem, ErrorResult& out_error)
|
||||
template<typename ElementT>
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, ElementT& elem,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
|
||||
&elem, &out_error);
|
||||
&elem, &out_rv);
|
||||
}
|
||||
|
||||
// WebGLTextureUpload.cpp
|
||||
bool ValidateTexImageSpecification(const char* funcName, uint8_t funcDims,
|
||||
GLenum texImageTarget, GLint level,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border,
|
||||
TexImageTarget* const out_target,
|
||||
WebGLTexture** const out_texture,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo);
|
||||
bool ValidateTexImageSelection(const char* funcName, uint8_t funcDims,
|
||||
GLenum texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLsizei width,
|
||||
GLsizei height, GLsizei depth,
|
||||
TexImageTarget* const out_target,
|
||||
WebGLTexture** const out_texture,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Vertices Feature (WebGLContextVertices.cpp)
|
||||
public:
|
||||
@ -1043,7 +1011,7 @@ private:
|
||||
GLsizei primcount, const char* info,
|
||||
GLuint* out_upperBound);
|
||||
bool DrawInstanced_check(const char* info);
|
||||
void Draw_cleanup(const char* funcName);
|
||||
void Draw_cleanup();
|
||||
|
||||
void VertexAttrib1fv_base(GLuint index, uint32_t arrayLength,
|
||||
const GLfloat* ptr);
|
||||
@ -1060,10 +1028,24 @@ private:
|
||||
// -----------------------------------------------------------------------------
|
||||
// PROTECTED
|
||||
protected:
|
||||
void SetFakeBlackStatus(WebGLContextFakeBlackStatus x) {
|
||||
mFakeBlackStatus = x;
|
||||
}
|
||||
// Returns the current fake-black-status, except if it was Unknown,
|
||||
// in which case this function resolves it first, so it never returns Unknown.
|
||||
WebGLContextFakeBlackStatus ResolvedFakeBlackStatus();
|
||||
|
||||
void BindFakeBlackTextures();
|
||||
void UnbindFakeBlackTextures();
|
||||
|
||||
WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need();
|
||||
bool DoFakeVertexAttrib0(GLuint vertexCount);
|
||||
void UndoFakeVertexAttrib0();
|
||||
|
||||
static CheckedUint32 GetImageSize(GLsizei height, GLsizei width,
|
||||
GLsizei depth, uint32_t pixelSize,
|
||||
uint32_t alignment);
|
||||
|
||||
inline void InvalidateBufferFetching()
|
||||
{
|
||||
mBufferFetchingIsVerified = false;
|
||||
@ -1094,7 +1076,6 @@ protected:
|
||||
void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
|
||||
|
||||
GLuint mActiveTexture;
|
||||
GLenum mDefaultFB_DrawBuffer0;
|
||||
|
||||
// glGetError sources:
|
||||
bool mEmitContextLostErrorOnce;
|
||||
@ -1109,36 +1090,23 @@ protected:
|
||||
// some GL constants
|
||||
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;
|
||||
int32_t mGLMaxVaryingVectors;
|
||||
int32_t mGLMaxFragmentUniformVectors;
|
||||
int32_t mGLMaxVertexUniformVectors;
|
||||
int32_t mGLMaxColorAttachments;
|
||||
int32_t mGLMaxDrawBuffers;
|
||||
uint32_t mGLMaxTransformFeedbackSeparateAttribs;
|
||||
GLuint mGLMaxUniformBufferBindings;
|
||||
GLsizei mGLMaxSamples;
|
||||
|
||||
// What is supported:
|
||||
uint32_t mGLMaxColorAttachments;
|
||||
uint32_t mGLMaxDrawBuffers;
|
||||
// What we're allowing:
|
||||
uint32_t mImplMaxColorAttachments;
|
||||
uint32_t mImplMaxDrawBuffers;
|
||||
|
||||
public:
|
||||
GLenum LastColorAttachmentEnum() const {
|
||||
return LOCAL_GL_COLOR_ATTACHMENT0 + mImplMaxColorAttachments - 1;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// Texture sizes are often not actually the GL values. Let's be explicit that these
|
||||
// are implementation limits.
|
||||
uint32_t mImplMaxTextureSize;
|
||||
uint32_t mImplMaxCubeMapTextureSize;
|
||||
uint32_t mImplMax3DTextureSize;
|
||||
uint32_t mImplMaxArrayTextureLayers;
|
||||
uint32_t mImplMaxRenderbufferSize;
|
||||
GLuint mGLMax3DTextureSize;
|
||||
GLuint mGLMaxArrayTextureLayers;
|
||||
|
||||
public:
|
||||
GLuint MaxVertexAttribs() const {
|
||||
@ -1149,7 +1117,8 @@ public:
|
||||
return mGLMaxTextureUnits;
|
||||
}
|
||||
|
||||
bool IsFormatValidForFB(TexInternalFormat format) const;
|
||||
|
||||
bool IsFormatValidForFB(GLenum sizedFormat) const;
|
||||
|
||||
protected:
|
||||
// Represents current status of the context with respect to context loss.
|
||||
@ -1186,11 +1155,9 @@ protected:
|
||||
WebGLExtensionBase* EnableSupportedExtension(JSContext* js,
|
||||
WebGLExtensionID ext);
|
||||
|
||||
public:
|
||||
// returns true if the extension has been enabled by calling getExtension.
|
||||
bool IsExtensionEnabled(WebGLExtensionID ext) const;
|
||||
|
||||
protected:
|
||||
// returns true if the extension is supported for this JSContext (this decides what getSupportedExtensions exposes)
|
||||
bool IsExtensionSupported(JSContext* cx, WebGLExtensionID ext) const;
|
||||
bool IsExtensionSupported(WebGLExtensionID ext) const;
|
||||
@ -1240,8 +1207,8 @@ protected:
|
||||
WebGLintptr byteOffset, const char* info);
|
||||
bool ValidateStencilParamsForDrawCall();
|
||||
|
||||
bool ValidateCopyTexImage(TexInternalFormat srcFormat, TexInternalFormat dstformat,
|
||||
WebGLTexImageFunc func, WebGLTexDimensions dims);
|
||||
bool ValidateCopyTexImage(GLenum internalFormat, WebGLTexImageFunc func,
|
||||
WebGLTexDimensions dims);
|
||||
|
||||
bool ValidateSamplerParameterName(GLenum pname, const char* info);
|
||||
bool ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info);
|
||||
@ -1288,10 +1255,6 @@ protected:
|
||||
WebGLProgram* program,
|
||||
const char* funcName);
|
||||
|
||||
bool ValidateCurFBForRead(const char* funcName,
|
||||
const webgl::FormatUsageInfo** const out_format,
|
||||
uint32_t* const out_width, uint32_t* const out_height);
|
||||
|
||||
void Invalidate();
|
||||
void DestroyResourcesAndContext();
|
||||
|
||||
@ -1305,23 +1268,31 @@ protected:
|
||||
WebGLTexelFormat dstFormat, bool dstPremultiplied,
|
||||
size_t dstTexelSize);
|
||||
|
||||
public:
|
||||
template<class ElementType>
|
||||
nsLayoutUtils::SurfaceFromElementResult
|
||||
SurfaceFromElement(dom::Element* elem)
|
||||
{
|
||||
SurfaceFromElement(ElementType* element) {
|
||||
MOZ_ASSERT(element);
|
||||
|
||||
uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE;
|
||||
|
||||
if (mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
|
||||
if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE)
|
||||
flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
|
||||
|
||||
if (!mPixelStore_PremultiplyAlpha)
|
||||
if (!mPixelStorePremultiplyAlpha)
|
||||
flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA;
|
||||
|
||||
gfx::DrawTarget* idealDrawTarget = nullptr; // Don't care for now.
|
||||
return nsLayoutUtils::SurfaceFromElement(elem, flags, idealDrawTarget);
|
||||
return nsLayoutUtils::SurfaceFromElement(element, flags);
|
||||
}
|
||||
|
||||
protected:
|
||||
template<class ElementType>
|
||||
nsLayoutUtils::SurfaceFromElementResult
|
||||
SurfaceFromElement(ElementType& element) {
|
||||
return SurfaceFromElement(&element);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
|
||||
RefPtr<gfx::DataSourceSurface>& imageOut,
|
||||
WebGLTexelFormat* format);
|
||||
|
||||
// Returns false if `object` is null or not valid.
|
||||
template<class ObjectType>
|
||||
bool ValidateObject(const char* info, ObjectType* object);
|
||||
@ -1360,22 +1331,30 @@ private:
|
||||
virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) = 0;
|
||||
|
||||
protected:
|
||||
int32_t MaxTextureSizeForTarget(TexTarget target) const {
|
||||
return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSize
|
||||
: mGLMaxCubeMapTextureSize;
|
||||
}
|
||||
|
||||
int32_t
|
||||
MaxTextureLevelForTexImageTarget(TexImageTarget texImageTarget) const {
|
||||
const TexTarget target = TexImageTargetToTexTarget(texImageTarget);
|
||||
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, GLsizeiptr size, const GLvoid* data,
|
||||
GLenum usage);
|
||||
|
||||
public:
|
||||
void ForceLoseContext(bool simulateLoss = false);
|
||||
|
||||
protected:
|
||||
void ForceRestoreContext();
|
||||
|
||||
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
|
||||
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
|
||||
nsTArray<WebGLRefPtr<WebGLTexture> > mBound3DTextures;
|
||||
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DArrayTextures;
|
||||
nsTArray<WebGLRefPtr<WebGLSampler> > mBoundSamplers;
|
||||
|
||||
void ResolveTexturesForDraw() const;
|
||||
@ -1383,6 +1362,10 @@ protected:
|
||||
WebGLRefPtr<WebGLProgram> mCurrentProgram;
|
||||
RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
|
||||
|
||||
GLenum LastColorAttachment() const {
|
||||
return LOCAL_GL_COLOR_ATTACHMENT0 + mGLMaxColorAttachments - 1;
|
||||
}
|
||||
|
||||
bool ValidateFramebufferTarget(GLenum target, const char* const info);
|
||||
|
||||
WebGLRefPtr<WebGLFramebuffer> mBoundDrawFramebuffer;
|
||||
@ -1408,50 +1391,34 @@ protected:
|
||||
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
|
||||
|
||||
// PixelStore parameters
|
||||
uint32_t mPixelStore_UnpackImageHeight;
|
||||
uint32_t mPixelStore_UnpackSkipImages;
|
||||
uint32_t mPixelStore_UnpackRowLength;
|
||||
uint32_t mPixelStore_UnpackSkipRows;
|
||||
uint32_t mPixelStore_UnpackSkipPixels;
|
||||
uint32_t mPixelStore_UnpackAlignment;
|
||||
uint32_t mPixelStore_PackRowLength;
|
||||
uint32_t mPixelStore_PackSkipRows;
|
||||
uint32_t mPixelStore_PackSkipPixels;
|
||||
uint32_t mPixelStore_PackAlignment;
|
||||
uint32_t mPixelStorePackAlignment;
|
||||
uint32_t mPixelStoreUnpackAlignment;
|
||||
uint32_t mPixelStoreColorspaceConversion;
|
||||
bool mPixelStoreFlipY;
|
||||
bool mPixelStorePremultiplyAlpha;
|
||||
|
||||
CheckedUint32 GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height,
|
||||
uint32_t depth, uint8_t bytesPerPixel);
|
||||
WebGLContextFakeBlackStatus mFakeBlackStatus;
|
||||
|
||||
CheckedUint32 GetPackSize(uint32_t width, uint32_t height, uint8_t bytesPerPixel,
|
||||
CheckedUint32* const out_startOffset,
|
||||
CheckedUint32* const out_rowStride);
|
||||
|
||||
GLenum mPixelStore_ColorspaceConversion;
|
||||
bool mPixelStore_FlipY;
|
||||
bool mPixelStore_PremultiplyAlpha;
|
||||
|
||||
////////////////////////////////////
|
||||
class FakeBlackTexture {
|
||||
public:
|
||||
gl::GLContext* const mGL;
|
||||
const GLuint mGLName;
|
||||
GLuint mGLName;
|
||||
|
||||
FakeBlackTexture(gl::GLContext* gl, TexTarget target, FakeBlackType type);
|
||||
public:
|
||||
FakeBlackTexture(gl::GLContext* gl, TexTarget target, GLenum format);
|
||||
~FakeBlackTexture();
|
||||
GLuint GLName() const { return mGLName; }
|
||||
};
|
||||
|
||||
UniquePtr<FakeBlackTexture> mFakeBlack_2D_0000;
|
||||
UniquePtr<FakeBlackTexture> mFakeBlack_2D_0001;
|
||||
UniquePtr<FakeBlackTexture> mFakeBlack_CubeMap_0000;
|
||||
UniquePtr<FakeBlackTexture> mFakeBlack_CubeMap_0001;
|
||||
UniquePtr<FakeBlackTexture> mFakeBlack_3D_0000;
|
||||
UniquePtr<FakeBlackTexture> mFakeBlack_3D_0001;
|
||||
UniquePtr<FakeBlackTexture> mFakeBlack_2D_Array_0000;
|
||||
UniquePtr<FakeBlackTexture> mFakeBlack_2D_Array_0001;
|
||||
UniquePtr<FakeBlackTexture> mBlackOpaqueTexture2D;
|
||||
UniquePtr<FakeBlackTexture> mBlackOpaqueTextureCubeMap;
|
||||
UniquePtr<FakeBlackTexture> mBlackTransparentTexture2D;
|
||||
UniquePtr<FakeBlackTexture> mBlackTransparentTextureCubeMap;
|
||||
|
||||
void BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fakeBlack);
|
||||
|
||||
////////////////////////////////////
|
||||
void
|
||||
BindFakeBlackTexturesHelper(GLenum target,
|
||||
const nsTArray<WebGLRefPtr<WebGLTexture> >& boundTexturesArray,
|
||||
UniquePtr<FakeBlackTexture>& opaqueTextureScopedPtr,
|
||||
UniquePtr<FakeBlackTexture>& transparentTextureScopedPtr);
|
||||
|
||||
// Generic Vertex Attributes
|
||||
UniquePtr<GLenum[]> mVertexAttribType;
|
||||
@ -1567,19 +1534,10 @@ public:
|
||||
|
||||
public:
|
||||
UniquePtr<webgl::FormatUsageAuthority> mFormatUsage;
|
||||
|
||||
virtual UniquePtr<webgl::FormatUsageAuthority>
|
||||
CreateFormatUsage(gl::GLContext* gl) const = 0;
|
||||
virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage() const = 0;
|
||||
|
||||
// Friend list
|
||||
friend class ScopedCopyTexImageSource;
|
||||
friend class ScopedResolveTexturesForDraw;
|
||||
friend class ScopedUnpackReset;
|
||||
friend class webgl::TexUnpackBlob;
|
||||
friend class webgl::TexUnpackBytes;
|
||||
friend class webgl::TexUnpackSurface;
|
||||
friend class WebGLTexture;
|
||||
friend class WebGLFBAttachPoint;
|
||||
friend class WebGLFramebuffer;
|
||||
friend class WebGLRenderbuffer;
|
||||
friend class WebGLProgram;
|
||||
@ -1673,99 +1631,24 @@ WebGLContext::ValidateObject(const char* info, ObjectType* object)
|
||||
return ValidateObjectAssumeNonNull(info, object);
|
||||
}
|
||||
|
||||
// Returns `value` rounded to the next highest multiple of `multiple`.
|
||||
// AKA PadToAlignment, StrideForAlignment.
|
||||
template<typename V, typename M>
|
||||
V
|
||||
RoundUpToMultipleOf(const V& value, const M& multiple)
|
||||
{
|
||||
return ((value + multiple - 1) / multiple) * multiple;
|
||||
}
|
||||
size_t RoundUpToMultipleOf(size_t value, size_t multiple);
|
||||
|
||||
bool
|
||||
ValidateTexTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
|
||||
GLenum rawTexTarget, TexTarget* const out_texTarget,
|
||||
WebGLTexture** const out_tex);
|
||||
ValidateTexTarget(WebGLContext* webgl, GLenum rawTexTarget, const char* funcName,
|
||||
TexTarget* const out_texTarget, WebGLTexture** const out_tex);
|
||||
bool
|
||||
ValidateTexImageTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
|
||||
GLenum rawTexImageTarget, TexImageTarget* const out_texImageTarget,
|
||||
ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
|
||||
const char* funcName, TexImageTarget* const out_texImageTarget,
|
||||
WebGLTexture** const out_tex);
|
||||
|
||||
class UniqueBuffer
|
||||
{
|
||||
// Like UniquePtr<>, but for void* and malloc/calloc/free.
|
||||
void* mBuffer;
|
||||
|
||||
public:
|
||||
UniqueBuffer()
|
||||
: mBuffer(nullptr)
|
||||
{ }
|
||||
|
||||
MOZ_IMPLICIT UniqueBuffer(void* buffer)
|
||||
: mBuffer(buffer)
|
||||
{ }
|
||||
|
||||
~UniqueBuffer() {
|
||||
free(mBuffer);
|
||||
}
|
||||
|
||||
UniqueBuffer(UniqueBuffer&& other) {
|
||||
this->mBuffer = other.mBuffer;
|
||||
other.mBuffer = nullptr;
|
||||
}
|
||||
|
||||
UniqueBuffer& operator =(UniqueBuffer&& other) {
|
||||
free(this->mBuffer);
|
||||
this->mBuffer = other.mBuffer;
|
||||
other.mBuffer = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniqueBuffer& operator =(void* newBuffer) {
|
||||
free(this->mBuffer);
|
||||
this->mBuffer = newBuffer;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return bool(mBuffer); }
|
||||
|
||||
void* get() const { return mBuffer; }
|
||||
|
||||
UniqueBuffer(const UniqueBuffer& other) = delete; // construct using Move()!
|
||||
void operator =(const UniqueBuffer& other) = delete; // assign using Move()!
|
||||
};
|
||||
|
||||
class ScopedUnpackReset
|
||||
: public gl::ScopedGLWrapper<ScopedUnpackReset>
|
||||
{
|
||||
friend struct gl::ScopedGLWrapper<ScopedUnpackReset>;
|
||||
|
||||
protected:
|
||||
WebGLContext* const mWebGL;
|
||||
|
||||
public:
|
||||
explicit ScopedUnpackReset(WebGLContext* webgl);
|
||||
|
||||
protected:
|
||||
void UnwrapImpl();
|
||||
};
|
||||
// Returns x rounded to the next highest multiple of y.
|
||||
CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y);
|
||||
|
||||
void
|
||||
ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view,
|
||||
void** const out_data, size_t* const out_length,
|
||||
js::Scalar::Type* const out_type);
|
||||
|
||||
void
|
||||
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, bool respecifyTexture,
|
||||
TexImageTarget target, uint32_t level,
|
||||
const webgl::FormatUsageInfo* usage, uint32_t xOffset, uint32_t yOffset,
|
||||
uint32_t zOffset, uint32_t width, uint32_t height, uint32_t depth);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
@ -23,134 +23,13 @@ namespace mozilla {
|
||||
// For a Tegra workaround.
|
||||
static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
class ScopedResolveTexturesForDraw
|
||||
{
|
||||
struct TexRebindRequest
|
||||
{
|
||||
uint32_t texUnit;
|
||||
WebGLTexture* tex;
|
||||
};
|
||||
|
||||
WebGLContext* const mWebGL;
|
||||
std::vector<TexRebindRequest> mRebindRequests;
|
||||
|
||||
public:
|
||||
ScopedResolveTexturesForDraw(WebGLContext* webgl, const char* funcName,
|
||||
bool* const out_error);
|
||||
~ScopedResolveTexturesForDraw();
|
||||
};
|
||||
|
||||
ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
|
||||
const char* funcName,
|
||||
bool* const out_error)
|
||||
: mWebGL(webgl)
|
||||
{
|
||||
//typedef nsTArray<WebGLRefPtr<WebGLTexture>> TexturesT;
|
||||
typedef decltype(WebGLContext::mBound2DTextures) TexturesT;
|
||||
|
||||
const auto fnResolveAll = [this, funcName, out_error](const TexturesT& textures)
|
||||
{
|
||||
const auto len = textures.Length();
|
||||
for (uint32_t texUnit = 0; texUnit < len; ++texUnit) {
|
||||
WebGLTexture* tex = textures[texUnit];
|
||||
if (!tex)
|
||||
continue;
|
||||
|
||||
FakeBlackType fakeBlack;
|
||||
*out_error |= !tex->ResolveForDraw(funcName, texUnit, &fakeBlack);
|
||||
|
||||
if (fakeBlack == FakeBlackType::None)
|
||||
continue;
|
||||
|
||||
mWebGL->BindFakeBlack(texUnit, tex->Target(), fakeBlack);
|
||||
mRebindRequests.push_back({texUnit, tex});
|
||||
}
|
||||
};
|
||||
|
||||
*out_error = false;
|
||||
|
||||
fnResolveAll(mWebGL->mBound2DTextures);
|
||||
fnResolveAll(mWebGL->mBoundCubeMapTextures);
|
||||
fnResolveAll(mWebGL->mBound3DTextures);
|
||||
fnResolveAll(mWebGL->mBound2DArrayTextures);
|
||||
|
||||
if (*out_error) {
|
||||
mWebGL->ErrorOutOfMemory("%s: Failed to resolve textures for draw.", funcName);
|
||||
}
|
||||
}
|
||||
|
||||
ScopedResolveTexturesForDraw::~ScopedResolveTexturesForDraw()
|
||||
{
|
||||
if (!mRebindRequests.size())
|
||||
return;
|
||||
|
||||
gl::GLContext* gl = mWebGL->gl;
|
||||
|
||||
for (const auto& itr : mRebindRequests) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + itr.texUnit);
|
||||
gl->fBindTexture(itr.tex->Target().get(), itr.tex->mGLName);
|
||||
}
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mWebGL->mActiveTexture);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fakeBlack)
|
||||
{
|
||||
MOZ_ASSERT(fakeBlack == FakeBlackType::RGBA0000 ||
|
||||
fakeBlack == FakeBlackType::RGBA0001);
|
||||
|
||||
const auto fnGetSlot = [this, target, fakeBlack]() -> UniquePtr<FakeBlackTexture>*
|
||||
{
|
||||
switch (fakeBlack) {
|
||||
case FakeBlackType::RGBA0000:
|
||||
switch (target.get()) {
|
||||
case LOCAL_GL_TEXTURE_2D : return &mFakeBlack_2D_0000;
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP: return &mFakeBlack_CubeMap_0000;
|
||||
case LOCAL_GL_TEXTURE_3D : return &mFakeBlack_3D_0000;
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY: return &mFakeBlack_2D_Array_0000;
|
||||
default: return nullptr;
|
||||
}
|
||||
|
||||
case FakeBlackType::RGBA0001:
|
||||
switch (target.get()) {
|
||||
case LOCAL_GL_TEXTURE_2D : return &mFakeBlack_2D_0001;
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP: return &mFakeBlack_CubeMap_0001;
|
||||
case LOCAL_GL_TEXTURE_3D : return &mFakeBlack_3D_0001;
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY: return &mFakeBlack_2D_Array_0001;
|
||||
default: return nullptr;
|
||||
}
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
UniquePtr<FakeBlackTexture>* slot = fnGetSlot();
|
||||
if (!slot) {
|
||||
MOZ_CRASH("fnGetSlot failed.");
|
||||
}
|
||||
UniquePtr<FakeBlackTexture>& fakeBlackTex = *slot;
|
||||
|
||||
if (!fakeBlackTex) {
|
||||
fakeBlackTex.reset(new FakeBlackTexture(gl, target, fakeBlack));
|
||||
}
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + texUnit);
|
||||
gl->fBindTexture(target.get(), fakeBlackTex->mGLName);
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
bool
|
||||
WebGLContext::DrawInstanced_check(const char* info)
|
||||
{
|
||||
MOZ_ASSERT(IsWebGL2() ||
|
||||
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays));
|
||||
if (!mBufferFetchingHasPerVertex) {
|
||||
if ((IsWebGL2() ||
|
||||
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays)) &&
|
||||
!mBufferFetchingHasPerVertex)
|
||||
{
|
||||
/* http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_instanced_arrays.txt
|
||||
* If all of the enabled vertex attribute arrays that are bound to active
|
||||
* generic attributes in the program have a non-zero divisor, the draw
|
||||
@ -232,25 +111,25 @@ WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DrawInstanced_check(info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BindFakeBlackTextures();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
|
||||
{
|
||||
const char funcName[] = "drawArrays";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateDrawModeEnum(mode, funcName))
|
||||
if (!ValidateDrawModeEnum(mode, "drawArrays: mode"))
|
||||
return;
|
||||
|
||||
bool error;
|
||||
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
|
||||
if (error)
|
||||
return;
|
||||
|
||||
if (!DrawArrays_check(first, count, 1, funcName))
|
||||
if (!DrawArrays_check(first, count, 1, "drawArrays"))
|
||||
return;
|
||||
|
||||
RunContextLossTimer();
|
||||
@ -260,28 +139,19 @@ WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
|
||||
gl->fDrawArrays(mode, first, count);
|
||||
}
|
||||
|
||||
Draw_cleanup(funcName);
|
||||
Draw_cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
|
||||
{
|
||||
const char funcName[] = "drawArraysInstanced";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateDrawModeEnum(mode, funcName))
|
||||
if (!ValidateDrawModeEnum(mode, "drawArraysInstanced: mode"))
|
||||
return;
|
||||
|
||||
bool error;
|
||||
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
|
||||
if (error)
|
||||
return;
|
||||
|
||||
if (!DrawArrays_check(first, count, primcount, funcName))
|
||||
return;
|
||||
|
||||
if (!DrawInstanced_check(funcName))
|
||||
if (!DrawArrays_check(first, count, primcount, "drawArraysInstanced"))
|
||||
return;
|
||||
|
||||
RunContextLossTimer();
|
||||
@ -291,7 +161,7 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsiz
|
||||
gl->fDrawArraysInstanced(mode, first, count, primcount);
|
||||
}
|
||||
|
||||
Draw_cleanup(funcName);
|
||||
Draw_cleanup();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -314,40 +184,39 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type,
|
||||
}
|
||||
|
||||
// If count is 0, there's nothing to do.
|
||||
if (count == 0 || primcount == 0)
|
||||
if (count == 0 || primcount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t bytesPerElem = 0;
|
||||
switch (type) {
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
bytesPerElem = 1;
|
||||
break;
|
||||
CheckedUint32 checked_byteCount;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_SHORT:
|
||||
bytesPerElem = 2;
|
||||
break;
|
||||
GLsizei first = 0;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_INT:
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_element_index_uint)) {
|
||||
bytesPerElem = 4;
|
||||
if (type == LOCAL_GL_UNSIGNED_SHORT) {
|
||||
checked_byteCount = 2 * CheckedUint32(count);
|
||||
if (byteOffset % 2 != 0) {
|
||||
ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_SHORT (must be a multiple of 2)", info);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
first = byteOffset / 2;
|
||||
}
|
||||
|
||||
if (!bytesPerElem) {
|
||||
ErrorInvalidEnum("%s: Invalid `type`: 0x%04x", info, type);
|
||||
else if (type == LOCAL_GL_UNSIGNED_BYTE) {
|
||||
checked_byteCount = count;
|
||||
first = byteOffset;
|
||||
}
|
||||
else if (type == LOCAL_GL_UNSIGNED_INT && IsExtensionEnabled(WebGLExtensionID::OES_element_index_uint)) {
|
||||
checked_byteCount = 4 * CheckedUint32(count);
|
||||
if (byteOffset % 4 != 0) {
|
||||
ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_INT (must be a multiple of 4)", info);
|
||||
return false;
|
||||
}
|
||||
first = byteOffset / 4;
|
||||
}
|
||||
else {
|
||||
ErrorInvalidEnum("%s: type must be UNSIGNED_SHORT or UNSIGNED_BYTE", info);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (byteOffset % bytesPerElem != 0) {
|
||||
ErrorInvalidOperation("%s: `byteOffset` must be a multiple of the size of `type`",
|
||||
info);
|
||||
return false;
|
||||
}
|
||||
|
||||
const GLsizei first = byteOffset / bytesPerElem;
|
||||
const CheckedUint32 checked_byteCount = bytesPerElem * CheckedUint32(count);
|
||||
|
||||
if (!checked_byteCount.isValid()) {
|
||||
ErrorInvalidValue("%s: overflow in byteCount", info);
|
||||
return false;
|
||||
@ -423,6 +292,12 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DrawInstanced_check(info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BindFakeBlackTextures();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -430,21 +305,18 @@ void
|
||||
WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
|
||||
WebGLintptr byteOffset)
|
||||
{
|
||||
const char funcName[] = "drawElements";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateDrawModeEnum(mode, funcName))
|
||||
return;
|
||||
|
||||
bool error;
|
||||
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
|
||||
if (error)
|
||||
if (!ValidateDrawModeEnum(mode, "drawElements: mode"))
|
||||
return;
|
||||
|
||||
GLuint upperBound = 0;
|
||||
if (!DrawElements_check(count, type, byteOffset, 1, funcName, &upperBound))
|
||||
if (!DrawElements_check(count, type, byteOffset, 1, "drawElements",
|
||||
&upperBound))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RunContextLossTimer();
|
||||
|
||||
@ -460,31 +332,25 @@ WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
|
||||
}
|
||||
}
|
||||
|
||||
Draw_cleanup(funcName);
|
||||
Draw_cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
|
||||
WebGLintptr byteOffset, GLsizei primcount)
|
||||
{
|
||||
const char funcName[] = "drawElementsInstanced";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateDrawModeEnum(mode, funcName))
|
||||
return;
|
||||
|
||||
bool error;
|
||||
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
|
||||
if (error)
|
||||
if (!ValidateDrawModeEnum(mode, "drawElementsInstanced: mode"))
|
||||
return;
|
||||
|
||||
GLuint upperBound = 0;
|
||||
if (!DrawElements_check(count, type, byteOffset, primcount, funcName, &upperBound))
|
||||
return;
|
||||
|
||||
if (!DrawInstanced_check(funcName))
|
||||
if (!DrawElements_check(count, type, byteOffset, primcount,
|
||||
"drawElementsInstanced", &upperBound))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RunContextLossTimer();
|
||||
|
||||
@ -495,12 +361,13 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
|
||||
primcount);
|
||||
}
|
||||
|
||||
Draw_cleanup(funcName);
|
||||
Draw_cleanup();
|
||||
}
|
||||
|
||||
void WebGLContext::Draw_cleanup(const char* funcName)
|
||||
void WebGLContext::Draw_cleanup()
|
||||
{
|
||||
UndoFakeVertexAttrib0();
|
||||
UnbindFakeBlackTextures();
|
||||
|
||||
if (!mBoundDrawFramebuffer) {
|
||||
Invalidate();
|
||||
@ -519,29 +386,17 @@ void WebGLContext::Draw_cleanup(const char* funcName)
|
||||
}
|
||||
}
|
||||
|
||||
// Let's check for a really common error: Viewport is larger than the actual
|
||||
// destination framebuffer.
|
||||
uint32_t destWidth = mViewportWidth;
|
||||
uint32_t destHeight = mViewportHeight;
|
||||
|
||||
if (mBoundDrawFramebuffer) {
|
||||
const auto& fba = mBoundDrawFramebuffer->ColorAttachment(0);
|
||||
if (fba.IsDefined()) {
|
||||
fba.Size(&destWidth, &destHeight);
|
||||
}
|
||||
} else {
|
||||
destWidth = mWidth;
|
||||
destHeight = mHeight;
|
||||
}
|
||||
|
||||
if (mViewportWidth > int32_t(destWidth) ||
|
||||
mViewportHeight > int32_t(destHeight))
|
||||
{
|
||||
if (!mAlreadyWarnedAboutViewportLargerThanDest) {
|
||||
GenerateWarning("%s: Drawing to a destination rect smaller than the viewport"
|
||||
" rect. (This warning will only be given once)",
|
||||
funcName);
|
||||
mAlreadyWarnedAboutViewportLargerThanDest = true;
|
||||
// Let's check the viewport
|
||||
const WebGLRectangleObject* rect = CurValidDrawFBRectObject();
|
||||
if (rect) {
|
||||
if (mViewportWidth > rect->Width() ||
|
||||
mViewportHeight > rect->Height())
|
||||
{
|
||||
if (!mAlreadyWarnedAboutViewportLargerThanDest) {
|
||||
GenerateWarning("Drawing to a destination rect smaller than the viewport rect. "
|
||||
"(This warning will only be given once)");
|
||||
mAlreadyWarnedAboutViewportLargerThanDest = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -791,67 +646,145 @@ WebGLContext::UndoFakeVertexAttrib0()
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0);
|
||||
}
|
||||
|
||||
static GLuint
|
||||
CreateGLTexture(gl::GLContext* gl)
|
||||
WebGLContextFakeBlackStatus
|
||||
WebGLContext::ResolvedFakeBlackStatus()
|
||||
{
|
||||
MOZ_ASSERT(gl->IsCurrent());
|
||||
GLuint ret = 0;
|
||||
gl->fGenTextures(1, &ret);
|
||||
return ret;
|
||||
// handle this case first, it's the generic case
|
||||
if (MOZ_LIKELY(mFakeBlackStatus == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return mFakeBlackStatus;
|
||||
|
||||
if (mFakeBlackStatus == WebGLContextFakeBlackStatus::Needed)
|
||||
return mFakeBlackStatus;
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if ((mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) ||
|
||||
(mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded))
|
||||
{
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::Needed;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
}
|
||||
|
||||
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
|
||||
// that means that we do NOT need it.
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl, TexTarget target,
|
||||
FakeBlackType type)
|
||||
: mGL(gl)
|
||||
, mGLName(CreateGLTexture(gl))
|
||||
void
|
||||
WebGLContext::BindFakeBlackTexturesHelper(
|
||||
GLenum target,
|
||||
const nsTArray<WebGLRefPtr<WebGLTexture> > & boundTexturesArray,
|
||||
UniquePtr<FakeBlackTexture> & opaqueTextureScopedPtr,
|
||||
UniquePtr<FakeBlackTexture> & transparentTextureScopedPtr)
|
||||
{
|
||||
GLenum texFormat;
|
||||
switch (type) {
|
||||
case FakeBlackType::RGBA0000:
|
||||
texFormat = LOCAL_GL_RGBA;
|
||||
break;
|
||||
|
||||
case FakeBlackType::RGBA0001:
|
||||
texFormat = LOCAL_GL_RGB;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("bad type");
|
||||
}
|
||||
|
||||
gl::ScopedBindTexture scopedBind(mGL, mGLName, target.get());
|
||||
|
||||
mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
|
||||
mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
|
||||
|
||||
// We allocate our zeros on the heap, and we overallocate (16 bytes instead of 4) to
|
||||
// minimize the risk of running into a driver bug in texImage2D, as it is a bit
|
||||
// unusual maybe to create 1x1 textures, and the stack may not have the alignment that
|
||||
// TexImage2D expects.
|
||||
|
||||
const webgl::DriverUnpackInfo dui = {texFormat, texFormat, LOCAL_GL_UNSIGNED_BYTE};
|
||||
UniqueBuffer zeros = moz_xcalloc(1, 16); // Infallible allocation.
|
||||
|
||||
if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
const TexImageTarget curTarget = LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
|
||||
const GLenum error = DoTexImage(mGL, curTarget.get(), 0, &dui, 1, 1, 1,
|
||||
zeros.get());
|
||||
if (error)
|
||||
MOZ_CRASH("Unexpected error during FakeBlack creation.");
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if (!boundTexturesArray[i]) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
const GLenum error = DoTexImage(mGL, target.get(), 0, &dui, 1, 1, 1,
|
||||
zeros.get());
|
||||
if (error)
|
||||
MOZ_CRASH("Unexpected error during FakeBlack creation.");
|
||||
|
||||
WebGLTextureFakeBlackStatus s = boundTexturesArray[i]->ResolvedFakeBlackStatus();
|
||||
MOZ_ASSERT(s != WebGLTextureFakeBlackStatus::Unknown);
|
||||
|
||||
if (MOZ_LIKELY(s == WebGLTextureFakeBlackStatus::NotNeeded)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
|
||||
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().EffectiveInternalFormat());
|
||||
UniquePtr<FakeBlackTexture>&
|
||||
blackTexturePtr = alpha
|
||||
? transparentTextureScopedPtr
|
||||
: opaqueTextureScopedPtr;
|
||||
|
||||
if (!blackTexturePtr) {
|
||||
GLenum format = alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
|
||||
blackTexturePtr = MakeUnique<FakeBlackTexture>(gl, target, format);
|
||||
}
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(target,
|
||||
blackTexturePtr->GLName());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindFakeBlackTextures()
|
||||
{
|
||||
// this is the generic case: try to return early
|
||||
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return;
|
||||
|
||||
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_2D,
|
||||
mBound2DTextures,
|
||||
mBlackOpaqueTexture2D,
|
||||
mBlackTransparentTexture2D);
|
||||
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_CUBE_MAP,
|
||||
mBoundCubeMapTextures,
|
||||
mBlackOpaqueTextureCubeMap,
|
||||
mBlackTransparentTextureCubeMap);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::UnbindFakeBlackTextures()
|
||||
{
|
||||
// this is the generic case: try to return early
|
||||
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return;
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if (mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->mGLName);
|
||||
}
|
||||
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->mGLName);
|
||||
}
|
||||
}
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
|
||||
}
|
||||
|
||||
WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl, TexTarget target, GLenum format)
|
||||
: mGL(gl)
|
||||
, mGLName(0)
|
||||
{
|
||||
MOZ_ASSERT(format == LOCAL_GL_RGB || format == LOCAL_GL_RGBA);
|
||||
|
||||
mGL->MakeCurrent();
|
||||
GLuint formerBinding = 0;
|
||||
gl->GetUIntegerv(target == LOCAL_GL_TEXTURE_2D
|
||||
? LOCAL_GL_TEXTURE_BINDING_2D
|
||||
: LOCAL_GL_TEXTURE_BINDING_CUBE_MAP,
|
||||
&formerBinding);
|
||||
gl->fGenTextures(1, &mGLName);
|
||||
gl->fBindTexture(target.get(), mGLName);
|
||||
|
||||
// we allocate our zeros on the heap, and we overallocate (16 bytes instead of 4)
|
||||
// to minimize the risk of running into a driver bug in texImage2D, as it is
|
||||
// a bit unusual maybe to create 1x1 textures, and the stack may not have the alignment
|
||||
// that texImage2D expects.
|
||||
UniquePtr<uint8_t> zeros((uint8_t*)moz_xcalloc(1, 16));
|
||||
if (target == LOCAL_GL_TEXTURE_2D) {
|
||||
gl->fTexImage2D(target.get(), 0, format, 1, 1,
|
||||
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros.get());
|
||||
} else {
|
||||
for (GLuint i = 0; i < 6; ++i) {
|
||||
gl->fTexImage2D(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, 1, 1,
|
||||
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros.get());
|
||||
}
|
||||
}
|
||||
|
||||
gl->fBindTexture(target.get(), formerBinding);
|
||||
}
|
||||
|
||||
WebGLContext::FakeBlackTexture::~FakeBlackTexture()
|
||||
{
|
||||
mGL->MakeCurrent();
|
||||
mGL->fDeleteTextures(1, &mGLName);
|
||||
if (mGL) {
|
||||
mGL->MakeCurrent();
|
||||
mGL->fDeleteTextures(1, &mGLName);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -106,20 +106,46 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
||||
if (mDisableExtensions)
|
||||
return false;
|
||||
|
||||
// Extensions for both WebGL 1 and 2.
|
||||
switch (ext) {
|
||||
// In alphabetical order
|
||||
switch (ext) {
|
||||
// ANGLE_
|
||||
case WebGLExtensionID::ANGLE_instanced_arrays:
|
||||
return WebGLExtensionInstancedArrays::IsSupported(this);
|
||||
|
||||
// EXT_
|
||||
case WebGLExtensionID::EXT_blend_minmax:
|
||||
return WebGLExtensionBlendMinMax::IsSupported(this);
|
||||
case WebGLExtensionID::EXT_color_buffer_half_float:
|
||||
return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
|
||||
case WebGLExtensionID::EXT_frag_depth:
|
||||
return WebGLExtensionFragDepth::IsSupported(this);
|
||||
case WebGLExtensionID::EXT_shader_texture_lod:
|
||||
return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod);
|
||||
case WebGLExtensionID::EXT_sRGB:
|
||||
return WebGLExtensionSRGB::IsSupported(this);
|
||||
case WebGLExtensionID::EXT_texture_filter_anisotropic:
|
||||
return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic);
|
||||
|
||||
// OES_
|
||||
case WebGLExtensionID::OES_element_index_uint:
|
||||
return gl->IsSupported(gl::GLFeature::element_index_uint);
|
||||
case WebGLExtensionID::OES_standard_derivatives:
|
||||
return gl->IsSupported(gl::GLFeature::standard_derivatives);
|
||||
case WebGLExtensionID::OES_texture_float:
|
||||
return gl->IsSupported(gl::GLFeature::texture_float);
|
||||
case WebGLExtensionID::OES_texture_float_linear:
|
||||
return gl->IsSupported(gl::GLFeature::texture_float_linear);
|
||||
case WebGLExtensionID::OES_texture_half_float:
|
||||
// If we have Feature::texture_half_float, we must not be on ES2
|
||||
// and need to translate HALF_FLOAT_OES -> HALF_FLOAT. We do that
|
||||
// right before making the relevant calls.
|
||||
return gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float) ||
|
||||
gl->IsSupported(gl::GLFeature::texture_half_float);
|
||||
|
||||
case WebGLExtensionID::OES_texture_half_float_linear:
|
||||
return gl->IsSupported(gl::GLFeature::texture_half_float_linear);
|
||||
case WebGLExtensionID::OES_vertex_array_object:
|
||||
return true;
|
||||
|
||||
// WEBGL_
|
||||
case WebGLExtensionID::WEBGL_color_buffer_float:
|
||||
@ -141,6 +167,15 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
||||
case WebGLExtensionID::WEBGL_debug_renderer_info:
|
||||
return Preferences::GetBool("webgl.enable-debug-renderer-info", false);
|
||||
|
||||
case WebGLExtensionID::WEBGL_depth_texture:
|
||||
// WEBGL_depth_texture supports DEPTH_STENCIL textures
|
||||
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
|
||||
return false;
|
||||
|
||||
return gl->IsSupported(gl::GLFeature::depth_texture) ||
|
||||
gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
|
||||
case WebGLExtensionID::WEBGL_draw_buffers:
|
||||
return WebGLExtensionDrawBuffers::IsSupported(this);
|
||||
case WebGLExtensionID::WEBGL_lose_context:
|
||||
// We always support this extension.
|
||||
return true;
|
||||
@ -150,61 +185,14 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
||||
break;
|
||||
}
|
||||
|
||||
if (!IsWebGL2()) {
|
||||
// WebGL1-only extensions
|
||||
if (gfxPrefs::WebGLDraftExtensionsEnabled() || IsWebGL2()) {
|
||||
switch (ext) {
|
||||
// ANGLE_
|
||||
case WebGLExtensionID::ANGLE_instanced_arrays:
|
||||
return WebGLExtensionInstancedArrays::IsSupported(this);
|
||||
|
||||
// EXT_
|
||||
case WebGLExtensionID::EXT_blend_minmax:
|
||||
return WebGLExtensionBlendMinMax::IsSupported(this);
|
||||
case WebGLExtensionID::EXT_frag_depth:
|
||||
return WebGLExtensionFragDepth::IsSupported(this);
|
||||
case WebGLExtensionID::EXT_shader_texture_lod:
|
||||
return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod);
|
||||
case WebGLExtensionID::EXT_sRGB:
|
||||
return WebGLExtensionSRGB::IsSupported(this);
|
||||
|
||||
// OES_
|
||||
case WebGLExtensionID::OES_element_index_uint:
|
||||
return gl->IsSupported(gl::GLFeature::element_index_uint);
|
||||
case WebGLExtensionID::OES_standard_derivatives:
|
||||
return gl->IsSupported(gl::GLFeature::standard_derivatives);
|
||||
case WebGLExtensionID::OES_texture_float:
|
||||
return WebGLExtensionTextureFloat::IsSupported(this);
|
||||
case WebGLExtensionID::OES_texture_half_float:
|
||||
return WebGLExtensionTextureHalfFloat::IsSupported(this);
|
||||
|
||||
case WebGLExtensionID::OES_vertex_array_object:
|
||||
return true;
|
||||
|
||||
// WEBGL_
|
||||
case WebGLExtensionID::WEBGL_depth_texture:
|
||||
// WEBGL_depth_texture supports DEPTH_STENCIL textures
|
||||
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
|
||||
return false;
|
||||
|
||||
return gl->IsSupported(gl::GLFeature::depth_texture) ||
|
||||
gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
|
||||
case WebGLExtensionID::WEBGL_draw_buffers:
|
||||
return WebGLExtensionDrawBuffers::IsSupported(this);
|
||||
case WebGLExtensionID::EXT_disjoint_timer_query:
|
||||
return WebGLExtensionDisjointTimerQuery::IsSupported(this);
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
}
|
||||
|
||||
if (gfxPrefs::WebGLDraftExtensionsEnabled()) {
|
||||
switch (ext) {
|
||||
case WebGLExtensionID::EXT_disjoint_timer_query:
|
||||
return WebGLExtensionDisjointTimerQuery::IsSupported(this);
|
||||
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -137,80 +137,71 @@ WebGLContext::DepthMask(WebGLboolean b)
|
||||
void
|
||||
WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
|
||||
{
|
||||
const char funcName[] = "drawBuffers";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
const size_t buffersLength = buffers.Length();
|
||||
|
||||
if (!buffersLength) {
|
||||
return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers must not be empty)");
|
||||
}
|
||||
|
||||
if (!mBoundDrawFramebuffer) {
|
||||
// GLES 3.0.4 p186:
|
||||
// "If the GL is bound to the default framebuffer, then `n` must be 1 and the
|
||||
// constant must be BACK or NONE. [...] If DrawBuffers is supplied with a
|
||||
// constant other than BACK and NONE, or with a value of `n` other than 1, the
|
||||
// error INVALID_OPERATION is generated."
|
||||
if (buffers.Length() != 1) {
|
||||
ErrorInvalidOperation("%s: For the default framebuffer, `buffers` must have a"
|
||||
" length of 1.",
|
||||
funcName);
|
||||
return;
|
||||
// OK: we are rendering in the default framebuffer
|
||||
|
||||
/* EXT_draw_buffers :
|
||||
If the GL is bound to the default framebuffer, then <buffersLength> must be 1
|
||||
and the constant must be BACK or NONE. When draw buffer zero is
|
||||
BACK, color values are written into the sole buffer for single-
|
||||
buffered contexts, or into the back buffer for double-buffered
|
||||
contexts. If DrawBuffersEXT is supplied with a constant other than
|
||||
BACK and NONE, the error INVALID_OPERATION is generated.
|
||||
*/
|
||||
if (buffersLength != 1) {
|
||||
return ErrorInvalidValue("drawBuffers: invalid <buffers> (main framebuffer: buffers.length must be 1)");
|
||||
}
|
||||
|
||||
switch (buffers[0]) {
|
||||
case LOCAL_GL_NONE:
|
||||
case LOCAL_GL_BACK:
|
||||
break;
|
||||
|
||||
default:
|
||||
ErrorInvalidOperation("%s: For the default framebuffer, `buffers[0]` must be"
|
||||
" BACK or NONE.",
|
||||
funcName);
|
||||
if (buffers[0] == LOCAL_GL_NONE || buffers[0] == LOCAL_GL_BACK) {
|
||||
gl->Screen()->SetDrawBuffer(buffers[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
mDefaultFB_DrawBuffer0 = buffers[0];
|
||||
gl->Screen()->SetDrawBuffer(buffers[0]);
|
||||
return;
|
||||
return ErrorInvalidOperation("drawBuffers: invalid operation (main framebuffer: buffers[0] must be GL_NONE or GL_BACK)");
|
||||
}
|
||||
|
||||
// Framebuffer object (not default framebuffer)
|
||||
// OK: we are rendering in a framebuffer object
|
||||
|
||||
if (buffers.Length() > mImplMaxDrawBuffers) {
|
||||
// "An INVALID_VALUE error is generated if `n` is greater than MAX_DRAW_BUFFERS."
|
||||
ErrorInvalidValue("%s: `buffers` must have a length <= MAX_DRAW_BUFFERS.",
|
||||
funcName);
|
||||
return;
|
||||
if (buffersLength > size_t(mGLMaxDrawBuffers)) {
|
||||
/* EXT_draw_buffers :
|
||||
The maximum number of draw buffers is implementation-dependent. The
|
||||
number of draw buffers supported can be queried by calling
|
||||
GetIntegerv with the symbolic constant MAX_DRAW_BUFFERS_EXT. An
|
||||
INVALID_VALUE error is generated if <buffersLength> is greater than
|
||||
MAX_DRAW_BUFFERS_EXT.
|
||||
*/
|
||||
return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers.length > GL_MAX_DRAW_BUFFERS)");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < buffers.Length(); i++) {
|
||||
// "If the GL is bound to a draw framebuffer object, the `i`th buffer listed in
|
||||
// bufs must be COLOR_ATTACHMENTi or NONE. Specifying a buffer out of order,
|
||||
// BACK, or COLOR_ATTACHMENTm where `m` is greater than or equal to the value of
|
||||
// MAX_COLOR_ATTACHMENTS, will generate the error INVALID_OPERATION.
|
||||
|
||||
// WEBGL_draw_buffers:
|
||||
// "The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or
|
||||
// equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter."
|
||||
// This means that if buffers.Length() isn't larger than MaxDrawBuffers, it won't
|
||||
// be larger than MaxColorAttachments.
|
||||
for (uint32_t i = 0; i < buffersLength; i++)
|
||||
{
|
||||
/* EXT_draw_buffers :
|
||||
If the GL is bound to a draw framebuffer object, the <i>th buffer listed
|
||||
in <bufs> must be COLOR_ATTACHMENT<i>_EXT or NONE. Specifying a
|
||||
buffer out of order, BACK, or COLOR_ATTACHMENT<m>_EXT where <m> is
|
||||
greater than or equal to the value of MAX_COLOR_ATTACHMENTS_EXT,
|
||||
will generate the error INVALID_OPERATION.
|
||||
*/
|
||||
/* WEBGL_draw_buffers :
|
||||
The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter.
|
||||
*/
|
||||
if (buffers[i] != LOCAL_GL_NONE &&
|
||||
buffers[i] != LOCAL_GL_COLOR_ATTACHMENT0 + i)
|
||||
{
|
||||
ErrorInvalidOperation("%s: `buffers[i]` must be NONE or COLOR_ATTACHMENTi.",
|
||||
funcName);
|
||||
return;
|
||||
buffers[i] != GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + i)) {
|
||||
return ErrorInvalidOperation("drawBuffers: invalid operation (buffers[i] must be GL_NONE or GL_COLOR_ATTACHMENTi)");
|
||||
}
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
const GLenum* ptr = nullptr;
|
||||
if (buffers.Length()) {
|
||||
ptr = buffers.Elements();
|
||||
}
|
||||
|
||||
gl->fDrawBuffers(buffers.Length(), ptr);
|
||||
|
||||
const auto end = ptr + buffers.Length();
|
||||
mBoundDrawFramebuffer->mDrawBuffers.assign(ptr, end);
|
||||
gl->fDrawBuffers(buffersLength, buffers.Elements());
|
||||
}
|
||||
|
||||
void
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -77,9 +77,7 @@ WebGLContext::GetStencilBits(GLint* out_stencilBits)
|
||||
{
|
||||
*out_stencilBits = 0;
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (mBoundDrawFramebuffer->StencilAttachment().IsDefined() &&
|
||||
mBoundDrawFramebuffer->DepthStencilAttachment().IsDefined())
|
||||
{
|
||||
if (mBoundDrawFramebuffer->HasDepthStencilConflict()) {
|
||||
// Error, we don't know which stencil buffer's bits to use
|
||||
ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
|
||||
return false;
|
||||
@ -144,15 +142,15 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
|
||||
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
|
||||
if (pname == LOCAL_GL_MAX_COLOR_ATTACHMENTS) {
|
||||
return JS::Int32Value(mImplMaxColorAttachments);
|
||||
return JS::Int32Value(mGLMaxColorAttachments);
|
||||
|
||||
} else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS) {
|
||||
return JS::Int32Value(mImplMaxDrawBuffers);
|
||||
return JS::Int32Value(mGLMaxDrawBuffers);
|
||||
|
||||
} else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
|
||||
pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mImplMaxDrawBuffers))
|
||||
pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers))
|
||||
{
|
||||
GLint iv = 0;
|
||||
gl->fGetIntegerv(pname, &iv);
|
||||
@ -168,7 +166,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
|
||||
if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
|
||||
if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
|
||||
WebGLVertexArray* vao =
|
||||
(mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
|
||||
@ -176,7 +174,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
|
||||
if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
|
||||
if (pname == LOCAL_GL_TIMESTAMP_EXT) {
|
||||
GLuint64 iv = 0;
|
||||
gl->fGetInteger64v(pname, (GLint64*) &iv);
|
||||
@ -237,7 +235,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
|
||||
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
|
||||
if (pname == LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT) {
|
||||
GLint i = 0;
|
||||
gl->fGetIntegerv(pname, &i);
|
||||
@ -382,13 +380,13 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
return JS::Int32Value(i);
|
||||
}
|
||||
case LOCAL_GL_MAX_TEXTURE_SIZE:
|
||||
return JS::Int32Value(mImplMaxTextureSize);
|
||||
return JS::Int32Value(mGLMaxTextureSize);
|
||||
|
||||
case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
|
||||
return JS::Int32Value(mImplMaxCubeMapTextureSize);
|
||||
return JS::Int32Value(mGLMaxCubeMapTextureSize);
|
||||
|
||||
case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
|
||||
return JS::Int32Value(mImplMaxRenderbufferSize);
|
||||
return JS::Int32Value(mGLMaxRenderbufferSize);
|
||||
|
||||
case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
|
||||
return JS::Int32Value(mGLMaxVertexUniformVectors);
|
||||
@ -451,13 +449,13 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
|
||||
// bool, WebGL-specific
|
||||
case UNPACK_FLIP_Y_WEBGL:
|
||||
return JS::BooleanValue(mPixelStore_FlipY);
|
||||
return JS::BooleanValue(mPixelStoreFlipY);
|
||||
case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
|
||||
return JS::BooleanValue(mPixelStore_PremultiplyAlpha);
|
||||
return JS::BooleanValue(mPixelStorePremultiplyAlpha);
|
||||
|
||||
// uint, WebGL-specific
|
||||
case UNPACK_COLORSPACE_CONVERSION_WEBGL:
|
||||
return JS::NumberValue(uint32_t(mPixelStore_ColorspaceConversion));
|
||||
return JS::NumberValue(uint32_t(mPixelStoreColorspaceConversion));
|
||||
|
||||
////////////////////////////////
|
||||
// Complex values
|
||||
|
@ -52,43 +52,31 @@
|
||||
namespace mozilla {
|
||||
|
||||
static bool
|
||||
IsValidTexTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexTarget,
|
||||
TexTarget* const out)
|
||||
IsValidTexTarget(WebGLContext* webgl, GLenum rawTexTarget, TexTarget* const out)
|
||||
{
|
||||
uint8_t targetDims;
|
||||
|
||||
switch (rawTexTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP:
|
||||
targetDims = 2;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
if (!webgl->IsWebGL2())
|
||||
return false;
|
||||
|
||||
targetDims = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Some funcs (like GenerateMipmap) doesn't know the dimension, so don't check it.
|
||||
if (funcDims && targetDims != funcDims)
|
||||
return false;
|
||||
|
||||
*out = rawTexTarget;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsValidTexImageTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexImageTarget,
|
||||
IsValidTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
|
||||
TexImageTarget* const out)
|
||||
{
|
||||
uint8_t targetDims;
|
||||
|
||||
switch (rawTexImageTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
@ -97,38 +85,31 @@ IsValidTexImageTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexImageT
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
targetDims = 2;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
if (!webgl->IsWebGL2())
|
||||
return false;
|
||||
|
||||
targetDims = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetDims != funcDims)
|
||||
return false;
|
||||
|
||||
*out = rawTexImageTarget;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ValidateTexTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
|
||||
GLenum rawTexTarget, TexTarget* const out_texTarget,
|
||||
WebGLTexture** const out_tex)
|
||||
ValidateTexTarget(WebGLContext* webgl, GLenum rawTexTarget, const char* funcName,
|
||||
TexTarget* const out_texTarget, WebGLTexture** const out_tex)
|
||||
{
|
||||
if (webgl->IsContextLost())
|
||||
return false;
|
||||
|
||||
TexTarget texTarget;
|
||||
if (!IsValidTexTarget(webgl, funcDims, rawTexTarget, &texTarget)) {
|
||||
if (!IsValidTexTarget(webgl, rawTexTarget, &texTarget)) {
|
||||
webgl->ErrorInvalidEnum("%s: Invalid texTarget.", funcName);
|
||||
return false;
|
||||
}
|
||||
@ -145,15 +126,15 @@ ValidateTexTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
|
||||
}
|
||||
|
||||
bool
|
||||
ValidateTexImageTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
|
||||
GLenum rawTexImageTarget, TexImageTarget* const out_texImageTarget,
|
||||
ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
|
||||
const char* funcName, TexImageTarget* const out_texImageTarget,
|
||||
WebGLTexture** const out_tex)
|
||||
{
|
||||
if (webgl->IsContextLost())
|
||||
return false;
|
||||
|
||||
TexImageTarget texImageTarget;
|
||||
if (!IsValidTexImageTarget(webgl, funcDims, rawTexImageTarget, &texImageTarget)) {
|
||||
if (!IsValidTexImageTarget(webgl, rawTexImageTarget, &texImageTarget)) {
|
||||
webgl->ErrorInvalidEnum("%s: Invalid texImageTarget.", funcName);
|
||||
return false;
|
||||
}
|
||||
@ -169,7 +150,7 @@ ValidateTexImageTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDi
|
||||
return true;
|
||||
}
|
||||
|
||||
/*virtual*/ bool
|
||||
bool
|
||||
WebGLContext::IsTexParamValid(GLenum pname) const
|
||||
{
|
||||
switch (pname) {
|
||||
@ -203,38 +184,32 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
|
||||
// newTex->Target() returns a TexTarget, which will assert on invalid value.
|
||||
WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
|
||||
switch (rawTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
currentTexPtr = &mBound2DTextures[mActiveTexture];
|
||||
break;
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
currentTexPtr = &mBound2DTextures[mActiveTexture];
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP:
|
||||
currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
|
||||
break;
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP:
|
||||
currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
if (!IsWebGL2())
|
||||
return ErrorInvalidEnum("bindTexture: target TEXTURE_3D is only available in WebGL version 2.0 or newer");
|
||||
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
if (IsWebGL2())
|
||||
currentTexPtr = &mBound3DTextures[mActiveTexture];
|
||||
break;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
if (IsWebGL2())
|
||||
currentTexPtr = &mBound2DArrayTextures[mActiveTexture];
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
|
||||
}
|
||||
|
||||
if (!currentTexPtr) {
|
||||
ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
const TexTarget texTarget(rawTarget);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (newTex) {
|
||||
if (!newTex->BindTexture(texTarget))
|
||||
return;
|
||||
} else {
|
||||
if (newTex && !newTex->BindTexture(texTarget))
|
||||
return;
|
||||
|
||||
if (!newTex) {
|
||||
gl->fBindTexture(texTarget.get(), 0);
|
||||
}
|
||||
|
||||
@ -244,12 +219,9 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
|
||||
void
|
||||
WebGLContext::GenerateMipmap(GLenum rawTexTarget)
|
||||
{
|
||||
const char funcName[] = "generateMipmap";
|
||||
const uint8_t funcDims = 0;
|
||||
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
|
||||
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
|
||||
return;
|
||||
|
||||
tex->GenerateMipmap(texTarget);
|
||||
@ -258,12 +230,9 @@ WebGLContext::GenerateMipmap(GLenum rawTexTarget)
|
||||
JS::Value
|
||||
WebGLContext::GetTexParameter(GLenum rawTexTarget, GLenum pname)
|
||||
{
|
||||
const char funcName[] = "getTexParameter";
|
||||
const uint8_t funcDims = 0;
|
||||
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
|
||||
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
|
||||
return JS::NullValue();
|
||||
|
||||
if (!IsTexParamValid(pname)) {
|
||||
@ -292,12 +261,9 @@ WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname, GLint* maybeI
|
||||
{
|
||||
MOZ_ASSERT(maybeIntParam || maybeFloatParam);
|
||||
|
||||
const char funcName[] = "texParameter";
|
||||
const uint8_t funcDims = 0;
|
||||
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
|
||||
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
|
||||
return;
|
||||
|
||||
tex->TexParameter(texTarget, pname, maybeIntParam, maybeFloatParam);
|
||||
@ -308,232 +274,140 @@ WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname, GLint* maybeI
|
||||
// Uploads
|
||||
|
||||
|
||||
////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TexImage
|
||||
|
||||
void
|
||||
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_rv)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType, elem,
|
||||
out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult&)
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
const char funcName[] = "texImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = false;
|
||||
const GLint xOffset = 0;
|
||||
const GLint yOffset = 0;
|
||||
const GLint zOffset = 0;
|
||||
const GLsizei depth = 1;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, width, height, depth, border, unpackFormat,
|
||||
unpackType, maybeView);
|
||||
tex->TexImage2D(texImageTarget, level, internalFormat, width, height, border,
|
||||
unpackFormat, unpackType, maybeView, &out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
dom::ImageData* imageData, ErrorResult&)
|
||||
dom::ImageData* imageData, ErrorResult& out_rv)
|
||||
{
|
||||
const char funcName[] = "texImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = false;
|
||||
const GLint xOffset = 0;
|
||||
const GLint yOffset = 0;
|
||||
const GLint zOffset = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, unpackFormat, unpackType, imageData);
|
||||
tex->TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType,
|
||||
imageData, &out_rv);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TexSubImage
|
||||
|
||||
|
||||
void
|
||||
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_error)
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::Element* elem, ErrorResult* const out_rv)
|
||||
{
|
||||
const char funcName[] = "texImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = false;
|
||||
const GLint xOffset = 0;
|
||||
const GLint yOffset = 0;
|
||||
const GLint zOffset = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, unpackFormat, unpackType, elem, out_error);
|
||||
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
|
||||
elem, out_rv);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// TexSubImage
|
||||
|
||||
void
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLsizei width, GLsizei height,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult&)
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
const char funcName[] = "texSubImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = true;
|
||||
const GLenum internalFormat = 0;
|
||||
const GLint zOffset = 0;
|
||||
const GLsizei depth = 1;
|
||||
const GLint border = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, width, height, depth, border, unpackFormat,
|
||||
unpackType, maybeView);
|
||||
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, width, height,
|
||||
unpackFormat, unpackType, maybeView, &out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::ImageData* imageData, ErrorResult&)
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
const char funcName[] = "texSubImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = true;
|
||||
const GLenum internalFormat = 0;
|
||||
const GLint zOffset = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, unpackFormat, unpackType, imageData);
|
||||
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
|
||||
imageData, &out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::Element* elem, ErrorResult* const out_error)
|
||||
{
|
||||
const char funcName[] = "texSubImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSubImage = true;
|
||||
const GLenum internalFormat = 0;
|
||||
const GLint zOffset = 0;
|
||||
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, unpackFormat, unpackType, elem, out_error);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// CompressedTex(Sub)Image
|
||||
|
||||
void
|
||||
WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLint border,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
|
||||
{
|
||||
const char funcName[] = "compressedTexImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const GLsizei depth = 1;
|
||||
|
||||
tex->CompressedTexImage(funcName, target, level, internalFormat, width, height, depth,
|
||||
border, view);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLsizei width,
|
||||
GLsizei height, GLenum sizedUnpackFormat,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
|
||||
{
|
||||
const char funcName[] = "compressedTexSubImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const GLint zOffset = 0;
|
||||
const GLsizei depth = 1;
|
||||
|
||||
tex->CompressedTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width,
|
||||
height, depth, sizedUnpackFormat, view);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CopyTex(Sub)Image
|
||||
|
||||
|
||||
void
|
||||
WebGLContext::CopyTexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLint border)
|
||||
{
|
||||
const char funcName[] = "copyTexImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "copyTexImage2D",
|
||||
&texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
|
||||
tex->CopyTexImage2D(texImageTarget, level, internalFormat, x, y, width, height,
|
||||
border);
|
||||
}
|
||||
|
||||
void
|
||||
@ -541,21 +415,55 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOf
|
||||
GLint yOffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height)
|
||||
{
|
||||
const char funcName[] = "copyTexSubImage2D";
|
||||
const uint8_t funcDims = 2;
|
||||
|
||||
TexImageTarget target;
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
|
||||
&tex))
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "copyTexSubImage2D",
|
||||
&texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const GLint zOffset = 0;
|
||||
tex->CopyTexSubImage2D(texImageTarget, level, xOffset, yOffset, x, y, width, height);
|
||||
}
|
||||
|
||||
tex->CopyTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, x, y, width,
|
||||
height);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CompressedTex(Sub)Image
|
||||
|
||||
|
||||
void
|
||||
WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "compressedTexImage2D",
|
||||
&texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CompressedTexImage2D(texImageTarget, level, internalFormat, width, height,
|
||||
border, view);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLsizei width,
|
||||
GLsizei height, GLenum unpackFormat,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "compressedTexSubImage2D",
|
||||
&texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CompressedTexSubImage2D(texImageTarget, level, xOffset, yOffset, width, height,
|
||||
unpackFormat, view);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -27,10 +27,38 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool
|
||||
IsGLDepthFormat(TexInternalFormat internalformat)
|
||||
{
|
||||
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
|
||||
return unsizedformat == LOCAL_GL_DEPTH_COMPONENT;
|
||||
}
|
||||
|
||||
bool
|
||||
IsGLDepthStencilFormat(TexInternalFormat internalformat)
|
||||
{
|
||||
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
|
||||
return unsizedformat == LOCAL_GL_DEPTH_STENCIL;
|
||||
}
|
||||
|
||||
bool
|
||||
FormatHasAlpha(TexInternalFormat internalformat)
|
||||
{
|
||||
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
|
||||
return unsizedformat == LOCAL_GL_RGBA ||
|
||||
unsizedformat == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
unsizedformat == LOCAL_GL_ALPHA ||
|
||||
unsizedformat == LOCAL_GL_SRGB_ALPHA ||
|
||||
unsizedformat == LOCAL_GL_RGBA_INTEGER;
|
||||
}
|
||||
|
||||
TexTarget
|
||||
TexImageTargetToTexTarget(TexImageTarget texImageTarget)
|
||||
{
|
||||
switch (texImageTarget.get()) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
return texImageTarget.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:
|
||||
@ -38,9 +66,10 @@ TexImageTargetToTexTarget(TexImageTarget texImageTarget)
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
return LOCAL_GL_TEXTURE_CUBE_MAP;
|
||||
|
||||
default:
|
||||
return texImageTarget.get();
|
||||
MOZ_ASSERT(false, "Bad texture target");
|
||||
// Should be caught by the constructor for TexTarget
|
||||
return LOCAL_GL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +85,387 @@ StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
|
||||
return JS::StringValue(str);
|
||||
}
|
||||
|
||||
GLComponents::GLComponents(TexInternalFormat internalformat)
|
||||
{
|
||||
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
|
||||
mComponents = 0;
|
||||
|
||||
switch (unsizedformat.get()) {
|
||||
case LOCAL_GL_RGBA:
|
||||
case LOCAL_GL_RGBA4:
|
||||
case LOCAL_GL_RGBA8:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
// Luminance + Alpha can be converted
|
||||
// to and from RGBA
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
mComponents |= Components::Alpha;
|
||||
// Drops through
|
||||
case LOCAL_GL_RGB:
|
||||
case LOCAL_GL_RGB565:
|
||||
// Luminance can be converted to and from RGB
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
mComponents |= Components::Red | Components::Green | Components::Blue;
|
||||
break;
|
||||
case LOCAL_GL_ALPHA:
|
||||
mComponents |= Components::Alpha;
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_COMPONENT:
|
||||
mComponents |= Components::Depth;
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_STENCIL:
|
||||
mComponents |= Components::Stencil;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unhandled case - GLComponents");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLComponents::IsSubsetOf(const GLComponents& other) const
|
||||
{
|
||||
return (mComponents | other.mComponents) == other.mComponents;
|
||||
}
|
||||
|
||||
TexType
|
||||
TypeFromInternalFormat(TexInternalFormat internalformat)
|
||||
{
|
||||
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
|
||||
if (internalformat == table_effectiveinternalformat) { \
|
||||
return table_type; \
|
||||
}
|
||||
|
||||
#include "WebGLInternalFormatsTable.h"
|
||||
|
||||
// if we're here, then internalformat is not an effective internalformat i.e. is an unsized internalformat.
|
||||
return LOCAL_GL_NONE; // no size, no type
|
||||
}
|
||||
|
||||
TexInternalFormat
|
||||
UnsizedInternalFormatFromInternalFormat(TexInternalFormat internalformat)
|
||||
{
|
||||
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
|
||||
if (internalformat == table_effectiveinternalformat) { \
|
||||
return table_internalformat; \
|
||||
}
|
||||
|
||||
#include "WebGLInternalFormatsTable.h"
|
||||
|
||||
// if we're here, then internalformat is not an effective internalformat i.e. is an unsized internalformat.
|
||||
// so we can just return it.
|
||||
return internalformat;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the following two functions are inverse of each other:
|
||||
* EffectiveInternalFormatFromInternalFormatAndType and
|
||||
* InternalFormatAndTypeFromEffectiveInternalFormat both implement OpenGL ES 3.0.3 Table 3.2
|
||||
* but in opposite directions.
|
||||
*/
|
||||
TexInternalFormat
|
||||
EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat internalformat,
|
||||
TexType type)
|
||||
{
|
||||
MOZ_ASSERT(TypeFromInternalFormat(internalformat) == LOCAL_GL_NONE);
|
||||
|
||||
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
|
||||
if (internalformat == table_internalformat && type == table_type) { \
|
||||
return table_effectiveinternalformat; \
|
||||
}
|
||||
|
||||
#include "WebGLInternalFormatsTable.h"
|
||||
|
||||
// If we're here, that means that type was incompatible with the given internalformat.
|
||||
return LOCAL_GL_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
|
||||
TexInternalFormat* const out_internalformat,
|
||||
TexType* const out_type)
|
||||
{
|
||||
MOZ_ASSERT(TypeFromInternalFormat(effectiveinternalformat) != LOCAL_GL_NONE);
|
||||
|
||||
MOZ_ASSERT(out_internalformat);
|
||||
MOZ_ASSERT(out_type);
|
||||
|
||||
GLenum internalformat = LOCAL_GL_NONE;
|
||||
GLenum type = LOCAL_GL_NONE;
|
||||
|
||||
switch (effectiveinternalformat.get()) {
|
||||
|
||||
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
|
||||
case table_effectiveinternalformat: \
|
||||
internalformat = table_internalformat; \
|
||||
type = table_type; \
|
||||
break;
|
||||
|
||||
#include "WebGLInternalFormatsTable.h"
|
||||
|
||||
default:
|
||||
MOZ_CRASH(); // impossible to get here
|
||||
}
|
||||
|
||||
*out_internalformat = internalformat;
|
||||
*out_type = type;
|
||||
}
|
||||
|
||||
TexInternalFormat
|
||||
EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalformat,
|
||||
TexType type)
|
||||
{
|
||||
TexType typeOfInternalFormat = TypeFromInternalFormat(internalformat);
|
||||
if (typeOfInternalFormat == LOCAL_GL_NONE)
|
||||
return EffectiveInternalFormatFromUnsizedInternalFormatAndType(internalformat, type);
|
||||
|
||||
if (typeOfInternalFormat == type)
|
||||
return internalformat;
|
||||
|
||||
return LOCAL_GL_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert effective internalformat into GL function parameters
|
||||
* valid for underlying driver.
|
||||
*/
|
||||
void
|
||||
DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
|
||||
TexInternalFormat effectiveinternalformat,
|
||||
GLenum* const out_driverInternalFormat,
|
||||
GLenum* const out_driverFormat,
|
||||
GLenum* const out_driverType)
|
||||
{
|
||||
MOZ_ASSERT(out_driverInternalFormat);
|
||||
MOZ_ASSERT(out_driverFormat);
|
||||
MOZ_ASSERT(out_driverType);
|
||||
|
||||
TexInternalFormat unsizedinternalformat = LOCAL_GL_NONE;
|
||||
TexType type = LOCAL_GL_NONE;
|
||||
|
||||
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(effectiveinternalformat,
|
||||
&unsizedinternalformat,
|
||||
&type);
|
||||
|
||||
// driverType: almost always the generic type that we just got, except on ES
|
||||
// we must replace HALF_FLOAT by HALF_FLOAT_OES
|
||||
GLenum driverType = type.get();
|
||||
if (gl->IsGLES() && type == LOCAL_GL_HALF_FLOAT)
|
||||
driverType = LOCAL_GL_HALF_FLOAT_OES;
|
||||
|
||||
// driverFormat: always just the unsized internalformat that we just got
|
||||
GLenum driverFormat = unsizedinternalformat.get();
|
||||
|
||||
// driverInternalFormat: almost always the same as driverFormat, but on desktop GL,
|
||||
// in some cases we must pass a different value. On ES, they are equal by definition
|
||||
// as it is an error to pass internalformat!=format.
|
||||
GLenum driverInternalFormat = driverFormat;
|
||||
if (gl->IsCompatibilityProfile()) {
|
||||
// Cases where desktop OpenGL requires a tweak to 'format'
|
||||
if (driverFormat == LOCAL_GL_SRGB)
|
||||
driverFormat = LOCAL_GL_RGB;
|
||||
else if (driverFormat == LOCAL_GL_SRGB_ALPHA)
|
||||
driverFormat = LOCAL_GL_RGBA;
|
||||
|
||||
// WebGL2's new formats are not legal values for internalformat,
|
||||
// as using unsized internalformat is deprecated.
|
||||
if (driverFormat == LOCAL_GL_RED ||
|
||||
driverFormat == LOCAL_GL_RG ||
|
||||
driverFormat == LOCAL_GL_RED_INTEGER ||
|
||||
driverFormat == LOCAL_GL_RG_INTEGER ||
|
||||
driverFormat == LOCAL_GL_RGB_INTEGER ||
|
||||
driverFormat == LOCAL_GL_RGBA_INTEGER)
|
||||
{
|
||||
driverInternalFormat = effectiveinternalformat.get();
|
||||
}
|
||||
|
||||
// Cases where desktop OpenGL requires a sized internalformat,
|
||||
// as opposed to the unsized internalformat that had the same
|
||||
// GLenum value as 'format', in order to get the precise
|
||||
// semantics that we want. For example, for floating-point formats,
|
||||
// we seem to need a sized internalformat to get non-clamped floating
|
||||
// point texture sampling. Can't find the spec reference for that,
|
||||
// but that's at least the case on my NVIDIA driver version 331.
|
||||
if (unsizedinternalformat == LOCAL_GL_DEPTH_COMPONENT ||
|
||||
unsizedinternalformat == LOCAL_GL_DEPTH_STENCIL ||
|
||||
type == LOCAL_GL_FLOAT ||
|
||||
type == LOCAL_GL_HALF_FLOAT)
|
||||
{
|
||||
driverInternalFormat = effectiveinternalformat.get();
|
||||
}
|
||||
}
|
||||
|
||||
// OpenGL core profile removed texture formats ALPHA, LUMINANCE and LUMINANCE_ALPHA
|
||||
if (gl->IsCoreProfile()) {
|
||||
switch (driverFormat) {
|
||||
case LOCAL_GL_ALPHA:
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
driverInternalFormat = driverFormat = LOCAL_GL_RED;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
driverInternalFormat = driverFormat = LOCAL_GL_RG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*out_driverInternalFormat = driverInternalFormat;
|
||||
*out_driverFormat = driverFormat;
|
||||
*out_driverType = driverType;
|
||||
}
|
||||
|
||||
// Map R to A
|
||||
static const GLenum kLegacyAlphaSwizzle[4] = {
|
||||
LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_RED
|
||||
};
|
||||
// Map R to RGB
|
||||
static const GLenum kLegacyLuminanceSwizzle[4] = {
|
||||
LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_ONE
|
||||
};
|
||||
// Map R to RGB, G to A
|
||||
static const GLenum kLegacyLuminanceAlphaSwizzle[4] = {
|
||||
LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_GREEN
|
||||
};
|
||||
|
||||
void
|
||||
SetLegacyTextureSwizzle(gl::GLContext* gl, GLenum target, GLenum internalformat)
|
||||
{
|
||||
if (!gl->IsCoreProfile())
|
||||
return;
|
||||
|
||||
/* Only support swizzling on core profiles. */
|
||||
// Bug 1159117: Fix this.
|
||||
// MOZ_RELEASE_ASSERT(gl->IsSupported(gl::GLFeature::texture_swizzle));
|
||||
|
||||
switch (internalformat) {
|
||||
case LOCAL_GL_ALPHA:
|
||||
gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA,
|
||||
(GLint*) kLegacyAlphaSwizzle);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA,
|
||||
(GLint*) kLegacyLuminanceSwizzle);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA,
|
||||
(GLint*) kLegacyLuminanceAlphaSwizzle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bits per texel for format & type combination.
|
||||
* Assumes that format & type are a valid combination as checked with
|
||||
* ValidateTexImageFormatAndType().
|
||||
*/
|
||||
size_t
|
||||
GetBitsPerTexel(TexInternalFormat effectiveinternalformat)
|
||||
{
|
||||
switch (effectiveinternalformat.get()) {
|
||||
case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
|
||||
return 2;
|
||||
|
||||
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
case LOCAL_GL_ATC_RGB:
|
||||
case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
|
||||
case LOCAL_GL_ETC1_RGB8_OES:
|
||||
return 4;
|
||||
|
||||
case LOCAL_GL_ALPHA8:
|
||||
case LOCAL_GL_LUMINANCE8:
|
||||
case LOCAL_GL_R8:
|
||||
case LOCAL_GL_R8I:
|
||||
case LOCAL_GL_R8UI:
|
||||
case LOCAL_GL_R8_SNORM:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
|
||||
case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
|
||||
return 8;
|
||||
|
||||
case LOCAL_GL_LUMINANCE8_ALPHA8:
|
||||
case LOCAL_GL_RGBA4:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||
case LOCAL_GL_RG8:
|
||||
case LOCAL_GL_R16I:
|
||||
case LOCAL_GL_R16UI:
|
||||
case LOCAL_GL_RGB565:
|
||||
case LOCAL_GL_R16F:
|
||||
case LOCAL_GL_RG8I:
|
||||
case LOCAL_GL_RG8UI:
|
||||
case LOCAL_GL_RG8_SNORM:
|
||||
case LOCAL_GL_ALPHA16F_EXT:
|
||||
case LOCAL_GL_LUMINANCE16F_EXT:
|
||||
return 16;
|
||||
|
||||
case LOCAL_GL_RGB8:
|
||||
case LOCAL_GL_DEPTH_COMPONENT24:
|
||||
case LOCAL_GL_SRGB8:
|
||||
case LOCAL_GL_RGB8UI:
|
||||
case LOCAL_GL_RGB8I:
|
||||
case LOCAL_GL_RGB8_SNORM:
|
||||
return 24;
|
||||
|
||||
case LOCAL_GL_RGBA8:
|
||||
case LOCAL_GL_RGB10_A2:
|
||||
case LOCAL_GL_R32F:
|
||||
case LOCAL_GL_RG16F:
|
||||
case LOCAL_GL_R32I:
|
||||
case LOCAL_GL_R32UI:
|
||||
case LOCAL_GL_RG16I:
|
||||
case LOCAL_GL_RG16UI:
|
||||
case LOCAL_GL_DEPTH24_STENCIL8:
|
||||
case LOCAL_GL_R11F_G11F_B10F:
|
||||
case LOCAL_GL_RGB9_E5:
|
||||
case LOCAL_GL_SRGB8_ALPHA8:
|
||||
case LOCAL_GL_DEPTH_COMPONENT32F:
|
||||
case LOCAL_GL_RGBA8UI:
|
||||
case LOCAL_GL_RGBA8I:
|
||||
case LOCAL_GL_RGBA8_SNORM:
|
||||
case LOCAL_GL_RGB10_A2UI:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA16F_EXT:
|
||||
case LOCAL_GL_ALPHA32F_EXT:
|
||||
case LOCAL_GL_LUMINANCE32F_EXT:
|
||||
return 32;
|
||||
|
||||
case LOCAL_GL_DEPTH32F_STENCIL8:
|
||||
return 40;
|
||||
|
||||
case LOCAL_GL_RGB16F:
|
||||
case LOCAL_GL_RGB16UI:
|
||||
case LOCAL_GL_RGB16I:
|
||||
return 48;
|
||||
|
||||
case LOCAL_GL_RG32F:
|
||||
case LOCAL_GL_RG32I:
|
||||
case LOCAL_GL_RG32UI:
|
||||
case LOCAL_GL_RGBA16F:
|
||||
case LOCAL_GL_RGBA16UI:
|
||||
case LOCAL_GL_RGBA16I:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA32F_EXT:
|
||||
return 64;
|
||||
|
||||
case LOCAL_GL_RGB32F:
|
||||
case LOCAL_GL_RGB32UI:
|
||||
case LOCAL_GL_RGB32I:
|
||||
return 96;
|
||||
|
||||
case LOCAL_GL_RGBA32F:
|
||||
case LOCAL_GL_RGBA32UI:
|
||||
case LOCAL_GL_RGBA32I:
|
||||
return 128;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unhandled format");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GenerateWarning(const char* fmt, ...)
|
||||
{
|
||||
@ -110,6 +520,27 @@ WebGLContext::ShouldGenerateWarnings() const
|
||||
return mAlreadyGeneratedWarnings < mMaxWarnings;
|
||||
}
|
||||
|
||||
CheckedUint32
|
||||
WebGLContext::GetImageSize(GLsizei height, GLsizei width, GLsizei depth,
|
||||
uint32_t pixelSize, uint32_t packOrUnpackAlignment)
|
||||
{
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * pixelSize;
|
||||
|
||||
// alignedRowSize = row size rounded up to next multiple of packAlignment
|
||||
CheckedUint32 checked_alignedRowSize = RoundedToNextMultipleOf(checked_plainRowSize, packOrUnpackAlignment);
|
||||
|
||||
// if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
|
||||
CheckedUint32 checked_2dImageSize = 0;
|
||||
if (height >= 1) {
|
||||
checked_2dImageSize = (height-1) * checked_alignedRowSize +
|
||||
checked_plainRowSize;
|
||||
}
|
||||
|
||||
// FIXME - we should honor UNPACK_IMAGE_HEIGHT
|
||||
CheckedUint32 checked_imageSize = checked_2dImageSize * depth;
|
||||
return checked_imageSize;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::SynthesizeGLError(GLenum err)
|
||||
{
|
||||
@ -681,7 +1112,7 @@ WebGLContext::AssertCachedBindings()
|
||||
|
||||
GetAndFlushUnderlyingGLErrors();
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
|
||||
if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
|
||||
GLuint bound = mBoundVertexArray ? mBoundVertexArray->GLName() : 0;
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
|
||||
}
|
||||
@ -737,20 +1168,10 @@ WebGLContext::AssertCachedState()
|
||||
|
||||
GetAndFlushUnderlyingGLErrors();
|
||||
|
||||
////////////////
|
||||
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_MAX_COLOR_ATTACHMENTS, mGLMaxColorAttachments);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_MAX_DRAW_BUFFERS, mGLMaxDrawBuffers);
|
||||
|
||||
if (IsWebGL2() ||
|
||||
IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
|
||||
{
|
||||
MOZ_ASSERT(mImplMaxColorAttachments == std::min(mGLMaxColorAttachments,
|
||||
mGLMaxDrawBuffers));
|
||||
MOZ_ASSERT(mImplMaxDrawBuffers == mGLMaxDrawBuffers);
|
||||
} else {
|
||||
MOZ_ASSERT(mImplMaxColorAttachments == 1);
|
||||
MOZ_ASSERT(mImplMaxDrawBuffers == 1);
|
||||
// extensions
|
||||
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_MAX_COLOR_ATTACHMENTS, mGLMaxColorAttachments);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_MAX_DRAW_BUFFERS, mGLMaxDrawBuffers);
|
||||
}
|
||||
|
||||
// Draw state
|
||||
@ -813,19 +1234,8 @@ WebGLContext::AssertCachedState()
|
||||
int4[2] == mViewportWidth &&
|
||||
int4[3] == mViewportHeight);
|
||||
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStore_PackAlignment);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStore_UnpackAlignment);
|
||||
|
||||
if (IsWebGL2()) {
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_IMAGE_HEIGHT, mPixelStore_UnpackImageHeight);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_IMAGES , mPixelStore_UnpackSkipImages);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ROW_LENGTH , mPixelStore_UnpackRowLength);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_ROWS , mPixelStore_UnpackSkipRows);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_PIXELS , mPixelStore_UnpackSkipPixels);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ROW_LENGTH , mPixelStore_PackRowLength);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_PACK_SKIP_ROWS , mPixelStore_PackSkipRows);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_PACK_SKIP_PIXELS , mPixelStore_PackSkipPixels);
|
||||
}
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStorePackAlignment);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStoreUnpackAlignment);
|
||||
|
||||
MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
|
||||
#endif
|
||||
|
@ -15,6 +15,35 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool IsGLDepthFormat(TexInternalFormat webGLFormat);
|
||||
bool IsGLDepthStencilFormat(TexInternalFormat webGLFormat);
|
||||
bool FormatHasAlpha(TexInternalFormat webGLFormat);
|
||||
|
||||
void
|
||||
DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
|
||||
TexInternalFormat internalformat,
|
||||
GLenum* const out_driverInternalFormat,
|
||||
GLenum* const out_driverFormat,
|
||||
GLenum* const out_driverType);
|
||||
TexInternalFormat
|
||||
EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalformat,
|
||||
TexType type);
|
||||
TexInternalFormat
|
||||
EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat internalformat,
|
||||
TexType type);
|
||||
void
|
||||
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
|
||||
TexInternalFormat* const out_internalformat,
|
||||
TexType* const out_type);
|
||||
TexType TypeFromInternalFormat(TexInternalFormat internalformat);
|
||||
|
||||
TexInternalFormat
|
||||
UnsizedInternalFormatFromInternalFormat(TexInternalFormat internalformat);
|
||||
|
||||
void SetLegacyTextureSwizzle(gl::GLContext* gl, GLenum target, GLenum internalformat);
|
||||
|
||||
size_t GetBitsPerTexel(TexInternalFormat effectiveinternalformat);
|
||||
|
||||
// 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
|
||||
@ -32,6 +61,9 @@ TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
|
||||
// Helper function to create a JS::Value from a C string
|
||||
JS::Value StringValue(JSContext* cx, const char* str, ErrorResult& rv);
|
||||
|
||||
bool IsCompressedTextureFormat(GLenum format);
|
||||
bool IsTextureFormatCompressed(TexInternalFormat format);
|
||||
|
||||
struct GLComponents
|
||||
{
|
||||
unsigned char mComponents;
|
||||
@ -64,7 +96,7 @@ WebGLContext::WebGLObjectAsJSValue(JSContext* cx, const WebGLObjectType* object,
|
||||
if (!object)
|
||||
return JS::NullValue();
|
||||
|
||||
MOZ_ASSERT(this == object->mContext);
|
||||
MOZ_ASSERT(this == object->Context());
|
||||
JS::Rooted<JS::Value> v(cx);
|
||||
JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
|
||||
JSAutoCompartment ac(cx, wrapper);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -358,11 +358,8 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
return JS::NumberValue(uint32_t(mBoundVertexArray->mAttribs[index].type));
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
|
||||
if (IsWebGL2() ||
|
||||
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
|
||||
{
|
||||
if (IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
|
||||
return JS::Int32Value(mBoundVertexArray->mAttribs[index].divisor);
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
|
||||
|
@ -9,31 +9,32 @@
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLFormats.h"
|
||||
|
||||
#ifdef FOO
|
||||
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using mozilla::webgl::EffectiveFormat;
|
||||
|
||||
WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
|
||||
|
||||
auto& fua = webgl->mFormatUsage;
|
||||
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
|
||||
|
||||
auto fnUpdateUsage = [&fua](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->isRenderable = true;
|
||||
fua->AllowRBFormat(sizedFormat, usage);
|
||||
auto updateUsage = [authority](EffectiveFormat effectiveFormat) {
|
||||
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
|
||||
MOZ_ASSERT(usage);
|
||||
usage->asRenderbuffer = usage->isRenderable = true;
|
||||
};
|
||||
|
||||
#define FOO(x) fnUpdateUsage(LOCAL_GL_ ## x, webgl::EffectiveFormat::x)
|
||||
// Ensure require formats are initialized.
|
||||
WebGLExtensionTextureFloat::InitWebGLFormats(authority);
|
||||
|
||||
// The extension doesn't actually add RGB32F; only RGBA32F.
|
||||
FOO(RGBA32F);
|
||||
|
||||
#undef FOO
|
||||
// Update usage to allow asRenderbuffer and isRenderable
|
||||
updateUsage(EffectiveFormat::RGBA32F);
|
||||
updateUsage(EffectiveFormat::RGB32F);
|
||||
updateUsage(EffectiveFormat::Luminance32FAlpha32F);
|
||||
updateUsage(EffectiveFormat::Luminance32F);
|
||||
updateUsage(EffectiveFormat::Alpha32F);
|
||||
}
|
||||
|
||||
WebGLExtensionColorBufferFloat::~WebGLExtensionColorBufferFloat()
|
||||
|
@ -9,31 +9,32 @@
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLFormats.h"
|
||||
|
||||
#ifdef FOO
|
||||
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using mozilla::webgl::EffectiveFormat;
|
||||
|
||||
WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
|
||||
|
||||
auto& fua = webgl->mFormatUsage;
|
||||
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
|
||||
|
||||
auto fnUpdateUsage = [&fua](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->isRenderable = true;
|
||||
fua->AllowRBFormat(sizedFormat, usage);
|
||||
auto updateUsage = [authority](EffectiveFormat effectiveFormat) {
|
||||
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
|
||||
MOZ_ASSERT(usage);
|
||||
usage->asRenderbuffer = usage->isRenderable = true;
|
||||
};
|
||||
|
||||
#define FOO(x) fnUpdateUsage(LOCAL_GL_ ## x, webgl::EffectiveFormat::x)
|
||||
// Ensure require formats are initialized.
|
||||
WebGLExtensionTextureHalfFloat::InitWebGLFormats(authority);
|
||||
|
||||
FOO(RGBA16F);
|
||||
FOO(RGB16F);
|
||||
|
||||
#undef FOO
|
||||
// Update usage to allow asRenderbuffer and isRenderable
|
||||
updateUsage(EffectiveFormat::RGBA16F);
|
||||
updateUsage(EffectiveFormat::RGB16F);
|
||||
updateUsage(EffectiveFormat::Luminance16FAlpha16F);
|
||||
updateUsage(EffectiveFormat::Luminance16F);
|
||||
updateUsage(EffectiveFormat::Alpha16F);
|
||||
}
|
||||
|
||||
WebGLExtensionColorBufferHalfFloat::~WebGLExtensionColorBufferHalfFloat()
|
||||
|
@ -7,33 +7,14 @@
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#ifdef FOO
|
||||
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
WebGLExtensionCompressedTextureATC::WebGLExtensionCompressedTextureATC(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
|
||||
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
|
||||
auto& fua = webgl_->mFormatUsage;
|
||||
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->isFilterable = true;
|
||||
fua->AllowSizedTexFormat(sizedFormat, usage);
|
||||
|
||||
webgl_->mCompressedTextureFormats.AppendElement(sizedFormat);
|
||||
};
|
||||
|
||||
#define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
|
||||
|
||||
fnAdd(FOO(ATC_RGB_AMD));
|
||||
fnAdd(FOO(ATC_RGBA_EXPLICIT_ALPHA_AMD));
|
||||
fnAdd(FOO(ATC_RGBA_INTERPOLATED_ALPHA_AMD));
|
||||
|
||||
#undef FOO
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGB);
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA);
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA);
|
||||
}
|
||||
|
||||
WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC()
|
||||
|
@ -7,31 +7,12 @@
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#ifdef FOO
|
||||
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
WebGLExtensionCompressedTextureETC1::WebGLExtensionCompressedTextureETC1(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
|
||||
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
|
||||
auto& fua = webgl_->mFormatUsage;
|
||||
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->isFilterable = true;
|
||||
fua->AllowSizedTexFormat(sizedFormat, usage);
|
||||
|
||||
webgl_->mCompressedTextureFormats.AppendElement(sizedFormat);
|
||||
};
|
||||
|
||||
#define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
|
||||
|
||||
fnAdd(FOO(ETC1_RGB8_OES));
|
||||
|
||||
#undef FOO
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ETC1_RGB8_OES);
|
||||
}
|
||||
|
||||
WebGLExtensionCompressedTextureETC1::~WebGLExtensionCompressedTextureETC1()
|
||||
|
@ -7,34 +7,15 @@
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#ifdef FOO
|
||||
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
|
||||
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
|
||||
auto& fua = webgl_->mFormatUsage;
|
||||
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->isFilterable = true;
|
||||
fua->AllowSizedTexFormat(sizedFormat, usage);
|
||||
|
||||
webgl_->mCompressedTextureFormats.AppendElement(sizedFormat);
|
||||
};
|
||||
|
||||
#define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
|
||||
|
||||
fnAdd(FOO(COMPRESSED_RGB_PVRTC_4BPPV1));
|
||||
fnAdd(FOO(COMPRESSED_RGB_PVRTC_2BPPV1));
|
||||
fnAdd(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1));
|
||||
fnAdd(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1));
|
||||
|
||||
#undef FOO
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1);
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1);
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1);
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1);
|
||||
}
|
||||
|
||||
WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()
|
||||
|
@ -7,34 +7,15 @@
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#ifdef FOO
|
||||
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
|
||||
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
|
||||
auto& fua = webgl_->mFormatUsage;
|
||||
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->isFilterable = true;
|
||||
fua->AllowSizedTexFormat(sizedFormat, usage);
|
||||
|
||||
webgl_->mCompressedTextureFormats.AppendElement(sizedFormat);
|
||||
};
|
||||
|
||||
#define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
|
||||
|
||||
fnAdd(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT));
|
||||
fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT));
|
||||
fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT));
|
||||
fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT));
|
||||
|
||||
#undef FOO
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
|
||||
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
|
||||
}
|
||||
|
||||
WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC()
|
||||
|
@ -13,29 +13,6 @@ namespace mozilla {
|
||||
WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
auto& fua = webgl->mFormatUsage;
|
||||
|
||||
const auto fnAdd = [&fua](webgl::EffectiveFormat effFormat, GLenum unpackFormat,
|
||||
GLenum unpackType)
|
||||
{
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->isRenderable = true;
|
||||
|
||||
const webgl::PackingInfo pi = {unpackFormat, unpackType};
|
||||
const webgl::DriverUnpackInfo dui = {unpackFormat, unpackFormat, unpackType};
|
||||
fua->AddTexUnpack(usage, pi, dui);
|
||||
|
||||
fua->AllowUnsizedTexFormat(pi, usage);
|
||||
};
|
||||
|
||||
fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT16, LOCAL_GL_DEPTH_COMPONENT,
|
||||
LOCAL_GL_UNSIGNED_SHORT);
|
||||
|
||||
fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT24, LOCAL_GL_DEPTH_COMPONENT,
|
||||
LOCAL_GL_UNSIGNED_INT);
|
||||
|
||||
fnAdd(webgl::EffectiveFormat::DEPTH24_STENCIL8, LOCAL_GL_DEPTH_STENCIL,
|
||||
LOCAL_GL_UNSIGNED_INT_24_8);
|
||||
}
|
||||
|
||||
WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture()
|
||||
|
@ -20,12 +20,26 @@ WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext* webgl)
|
||||
{
|
||||
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
|
||||
|
||||
// WEBGL_draw_buffers:
|
||||
// "The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or
|
||||
// equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter."
|
||||
webgl->mImplMaxColorAttachments = webgl->mGLMaxColorAttachments;
|
||||
webgl->mImplMaxDrawBuffers = std::min(webgl->mGLMaxDrawBuffers,
|
||||
webgl->mImplMaxColorAttachments);
|
||||
GLint maxColorAttachments = 0;
|
||||
GLint maxDrawBuffers = 0;
|
||||
|
||||
webgl->MakeContextCurrent();
|
||||
gl::GLContext* gl = webgl->GL();
|
||||
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
||||
|
||||
// WEBGL_draw_buffers specifications don't give a maximal value reachable by MAX_COLOR_ATTACHMENTS.
|
||||
maxColorAttachments = std::min(maxColorAttachments, GLint(WebGLContext::kMaxColorAttachments));
|
||||
|
||||
if (webgl->MinCapabilityMode())
|
||||
maxColorAttachments = std::min(maxColorAttachments, GLint(kMinColorAttachments));
|
||||
|
||||
// WEBGL_draw_buffers specifications request MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
|
||||
maxDrawBuffers = std::min(maxDrawBuffers, GLint(maxColorAttachments));
|
||||
|
||||
webgl->mGLMaxColorAttachments = maxColorAttachments;
|
||||
webgl->mGLMaxDrawBuffers = maxDrawBuffers;
|
||||
}
|
||||
|
||||
WebGLExtensionDrawBuffers::~WebGLExtensionDrawBuffers()
|
||||
@ -51,12 +65,20 @@ WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl)
|
||||
if (!gl->IsSupported(gl::GLFeature::draw_buffers))
|
||||
return false;
|
||||
|
||||
GLint supportedColorAttachments = 0;
|
||||
GLint supportedDrawBuffers = 0;
|
||||
|
||||
webgl->MakeContextCurrent();
|
||||
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &supportedColorAttachments);
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &supportedDrawBuffers);
|
||||
|
||||
// WEBGL_draw_buffers requires at least 4 color attachments.
|
||||
if (webgl->mGLMaxDrawBuffers < webgl->kMinMaxDrawBuffers ||
|
||||
webgl->mGLMaxColorAttachments < webgl->kMinMaxColorAttachments)
|
||||
{
|
||||
if (size_t(supportedColorAttachments) < kMinColorAttachments)
|
||||
return false;
|
||||
|
||||
if (size_t(supportedDrawBuffers) < kMinDrawBuffers)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -12,6 +12,9 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using mozilla::webgl::EffectiveFormat;
|
||||
|
||||
|
||||
WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
@ -25,32 +28,20 @@ WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* webgl)
|
||||
gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
|
||||
}
|
||||
|
||||
auto& fua = webgl->mFormatUsage;
|
||||
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
|
||||
|
||||
RefPtr<gl::GLContext> gl_ = gl; // Bug 1201275
|
||||
const auto fnAdd = [&fua, &gl_](webgl::EffectiveFormat effFormat, GLenum format,
|
||||
GLenum desktopUnpackFormat)
|
||||
{
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->isFilterable = true;
|
||||
auto addFormatIfMissing = [authority](EffectiveFormat effectiveFormat,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
bool asRenderbuffer)
|
||||
{
|
||||
if (!authority->GetUsage(effectiveFormat)) {
|
||||
authority->AddFormat(effectiveFormat, asRenderbuffer, asRenderbuffer, true, true);
|
||||
authority->AddUnpackOption(unpackFormat, unpackType, effectiveFormat);
|
||||
}
|
||||
};
|
||||
|
||||
webgl::DriverUnpackInfo dui = {format, format, LOCAL_GL_UNSIGNED_BYTE};
|
||||
const auto pi = dui.ToPacking();
|
||||
|
||||
if (!gl_->IsGLES())
|
||||
dui.unpackFormat = desktopUnpackFormat;
|
||||
|
||||
fua->AddTexUnpack(usage, pi, dui);
|
||||
|
||||
fua->AllowUnsizedTexFormat(pi, usage);
|
||||
};
|
||||
|
||||
fnAdd(webgl::EffectiveFormat::SRGB8, LOCAL_GL_SRGB, LOCAL_GL_RGB);
|
||||
fnAdd(webgl::EffectiveFormat::SRGB8_ALPHA8, LOCAL_GL_SRGB_ALPHA, LOCAL_GL_RGBA);
|
||||
|
||||
auto usage = fua->EditUsage(webgl::EffectiveFormat::SRGB8_ALPHA8);
|
||||
usage->isRenderable = true;
|
||||
fua->AllowRBFormat(LOCAL_GL_SRGB8_ALPHA8, usage);
|
||||
addFormatIfMissing(EffectiveFormat::SRGB8 , LOCAL_GL_SRGB , LOCAL_GL_UNSIGNED_BYTE, false);
|
||||
addFormatIfMissing(EffectiveFormat::SRGB8_ALPHA8, LOCAL_GL_SRGB_ALPHA, LOCAL_GL_UNSIGNED_BYTE, true);
|
||||
}
|
||||
|
||||
WebGLExtensionSRGB::~WebGLExtensionSRGB()
|
||||
|
@ -4,112 +4,63 @@
|
||||
|
||||
#include "WebGLExtensions.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLFormats.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using mozilla::webgl::EffectiveFormat;
|
||||
|
||||
void
|
||||
WebGLExtensionTextureFloat::InitWebGLFormats(webgl::FormatUsageAuthority* authority)
|
||||
{
|
||||
MOZ_ASSERT(authority);
|
||||
|
||||
auto addFormatIfMissing = [authority](EffectiveFormat effectiveFormat)
|
||||
{
|
||||
if (!authority->GetUsage(effectiveFormat)) {
|
||||
authority->AddFormat(effectiveFormat, false, false, false, false);
|
||||
}
|
||||
};
|
||||
|
||||
// Populate authority with any missing effective formats.
|
||||
addFormatIfMissing(EffectiveFormat::RGBA32F);
|
||||
addFormatIfMissing(EffectiveFormat::RGB32F);
|
||||
addFormatIfMissing(EffectiveFormat::Luminance32FAlpha32F);
|
||||
addFormatIfMissing(EffectiveFormat::Luminance32F);
|
||||
addFormatIfMissing(EffectiveFormat::Alpha32F);
|
||||
}
|
||||
|
||||
WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
MOZ_ASSERT(IsSupported(webgl));
|
||||
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
|
||||
|
||||
auto& fua = webgl->mFormatUsage;
|
||||
gl::GLContext* gl = webgl->GL();
|
||||
auto updateUsage = [authority](EffectiveFormat effectiveFormat,
|
||||
GLenum unpackFormat, GLenum unpackType)
|
||||
{
|
||||
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
|
||||
MOZ_ASSERT(usage);
|
||||
usage->asTexture = true;
|
||||
authority->AddUnpackOption(unpackFormat, unpackType, effectiveFormat);
|
||||
};
|
||||
|
||||
webgl::PackingInfo pi;
|
||||
webgl::DriverUnpackInfo dui;
|
||||
const GLint* swizzle = nullptr;
|
||||
// Ensure require formats are initialized.
|
||||
InitWebGLFormats(authority);
|
||||
|
||||
const auto fnAdd = [&fua, &pi, &dui, &swizzle](webgl::EffectiveFormat effFormat)
|
||||
{
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->textureSwizzleRGBA = swizzle;
|
||||
fua->AddTexUnpack(usage, pi, dui);
|
||||
|
||||
fua->AllowUnsizedTexFormat(pi, usage);
|
||||
};
|
||||
|
||||
const bool needSizedInternal = !gl->IsGLES();
|
||||
MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle));
|
||||
|
||||
////////////////
|
||||
|
||||
pi = {LOCAL_GL_RGBA, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui.internalFormat = LOCAL_GL_RGBA32F;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::RGBA32F);
|
||||
|
||||
//////
|
||||
|
||||
pi = {LOCAL_GL_RGB, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui.internalFormat = LOCAL_GL_RGB32F;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::RGB32F);
|
||||
|
||||
//////
|
||||
|
||||
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT};
|
||||
swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Luminance32F);
|
||||
|
||||
//////
|
||||
|
||||
pi = {LOCAL_GL_ALPHA, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT};
|
||||
swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Alpha32F);
|
||||
|
||||
//////
|
||||
|
||||
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui = {LOCAL_GL_RG32F, LOCAL_GL_RG, LOCAL_GL_FLOAT};
|
||||
swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F);
|
||||
// Update usage to allow asTexture and add unpack
|
||||
updateUsage(EffectiveFormat::RGBA32F , LOCAL_GL_RGBA , LOCAL_GL_FLOAT);
|
||||
updateUsage(EffectiveFormat::RGB32F , LOCAL_GL_RGB , LOCAL_GL_FLOAT);
|
||||
updateUsage(EffectiveFormat::Luminance32FAlpha32F, LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT);
|
||||
updateUsage(EffectiveFormat::Luminance32F , LOCAL_GL_LUMINANCE , LOCAL_GL_FLOAT);
|
||||
updateUsage(EffectiveFormat::Alpha32F , LOCAL_GL_ALPHA , LOCAL_GL_FLOAT);
|
||||
}
|
||||
|
||||
WebGLExtensionTextureFloat::~WebGLExtensionTextureFloat()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl)
|
||||
{
|
||||
gl::GLContext* gl = webgl->GL();
|
||||
|
||||
if (!gl->IsSupported(gl::GLFeature::texture_float))
|
||||
return false;
|
||||
|
||||
const bool needSizedInternal = !gl->IsGLES();
|
||||
const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
|
||||
|
||||
if (needSizedInternal && !hasSwizzle)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat, OES_texture_float)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -10,16 +10,32 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using mozilla::webgl::EffectiveFormat;
|
||||
|
||||
WebGLExtensionTextureFloatLinear::WebGLExtensionTextureFloatLinear(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
auto& fua = webgl->mFormatUsage;
|
||||
// This update requires that the authority already be populated by
|
||||
// WebGLExtensionTextureFloat. Enabling extensions to control
|
||||
// features is a mess in WebGL
|
||||
|
||||
fua->EditUsage(webgl::EffectiveFormat::RGBA32F)->isFilterable = true;
|
||||
fua->EditUsage(webgl::EffectiveFormat::RGB32F)->isFilterable = true;
|
||||
fua->EditUsage(webgl::EffectiveFormat::Luminance32FAlpha32F)->isFilterable = true;
|
||||
fua->EditUsage(webgl::EffectiveFormat::Luminance32F)->isFilterable = true;
|
||||
fua->EditUsage(webgl::EffectiveFormat::Alpha32F)->isFilterable = true;
|
||||
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
|
||||
|
||||
auto updateUsage = [authority](EffectiveFormat effectiveFormat) {
|
||||
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
|
||||
MOZ_ASSERT(usage);
|
||||
usage->isFilterable = true;
|
||||
};
|
||||
|
||||
// Ensure require formats are initialized.
|
||||
WebGLExtensionTextureFloat::InitWebGLFormats(authority);
|
||||
|
||||
// Update usage to allow isFilterable
|
||||
updateUsage(EffectiveFormat::RGBA32F);
|
||||
updateUsage(EffectiveFormat::RGB32F);
|
||||
updateUsage(EffectiveFormat::Luminance32FAlpha32F);
|
||||
updateUsage(EffectiveFormat::Luminance32F);
|
||||
updateUsage(EffectiveFormat::Alpha32F);
|
||||
}
|
||||
|
||||
WebGLExtensionTextureFloatLinear::~WebGLExtensionTextureFloatLinear()
|
||||
|
@ -4,119 +4,62 @@
|
||||
|
||||
#include "WebGLExtensions.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLFormats.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using mozilla::webgl::EffectiveFormat;
|
||||
|
||||
void
|
||||
WebGLExtensionTextureHalfFloat::InitWebGLFormats(webgl::FormatUsageAuthority* authority)
|
||||
{
|
||||
MOZ_ASSERT(authority);
|
||||
|
||||
auto addFormatIfMissing = [authority](EffectiveFormat effectiveFormat)
|
||||
{
|
||||
if (!authority->GetUsage(effectiveFormat)) {
|
||||
authority->AddFormat(effectiveFormat, false, false, false, false);
|
||||
}
|
||||
};
|
||||
|
||||
// Populate authority with any missing effective formats.
|
||||
addFormatIfMissing(EffectiveFormat::RGBA16F);
|
||||
addFormatIfMissing(EffectiveFormat::RGB16F);
|
||||
addFormatIfMissing(EffectiveFormat::Luminance16FAlpha16F);
|
||||
addFormatIfMissing(EffectiveFormat::Luminance16F);
|
||||
addFormatIfMissing(EffectiveFormat::Alpha16F);
|
||||
}
|
||||
|
||||
WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
auto& fua = webgl->mFormatUsage;
|
||||
gl::GLContext* gl = webgl->GL();
|
||||
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
|
||||
|
||||
webgl::PackingInfo pi;
|
||||
webgl::DriverUnpackInfo dui;
|
||||
const GLint* swizzle = nullptr;
|
||||
auto updateUsage = [authority](EffectiveFormat effectiveFormat,
|
||||
GLenum unpackFormat, GLenum unpackType)
|
||||
{
|
||||
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
|
||||
MOZ_ASSERT(usage);
|
||||
usage->asTexture = true;
|
||||
authority->AddUnpackOption(unpackFormat, unpackType, effectiveFormat);
|
||||
};
|
||||
|
||||
const auto fnAdd = [&fua, &pi, &dui, &swizzle](webgl::EffectiveFormat effFormat)
|
||||
{
|
||||
auto usage = fua->EditUsage(effFormat);
|
||||
usage->textureSwizzleRGBA = swizzle;
|
||||
fua->AddTexUnpack(usage, pi, dui);
|
||||
InitWebGLFormats(authority);
|
||||
|
||||
fua->AllowUnsizedTexFormat(pi, usage);
|
||||
};
|
||||
|
||||
const bool needSizedInternal = !gl->IsGLES();
|
||||
MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle));
|
||||
|
||||
GLenum driverUnpackType = LOCAL_GL_HALF_FLOAT;
|
||||
if (!gl->IsSupported(gl::GLFeature::texture_half_float)) {
|
||||
MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
|
||||
driverUnpackType = LOCAL_GL_HALF_FLOAT_OES;
|
||||
}
|
||||
|
||||
////////////////
|
||||
|
||||
pi = {LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui.internalFormat = LOCAL_GL_RGBA16F;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::RGBA16F);
|
||||
|
||||
//////
|
||||
|
||||
pi = {LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui.internalFormat = LOCAL_GL_RGB16F;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::RGB16F);
|
||||
|
||||
//////
|
||||
|
||||
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType};
|
||||
swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Luminance16F);
|
||||
|
||||
//////
|
||||
|
||||
pi = {LOCAL_GL_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType};
|
||||
swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Alpha16F);
|
||||
|
||||
//////
|
||||
|
||||
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
dui = {LOCAL_GL_RG16F, LOCAL_GL_RG, driverUnpackType};
|
||||
swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F);
|
||||
// Update usage to allow asTexture and add unpack
|
||||
updateUsage(EffectiveFormat::RGBA16F , LOCAL_GL_RGBA , LOCAL_GL_HALF_FLOAT_OES);
|
||||
updateUsage(EffectiveFormat::RGB16F , LOCAL_GL_RGB , LOCAL_GL_HALF_FLOAT_OES);
|
||||
updateUsage(EffectiveFormat::Luminance16FAlpha16F, LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES);
|
||||
updateUsage(EffectiveFormat::Luminance16F , LOCAL_GL_LUMINANCE , LOCAL_GL_HALF_FLOAT_OES);
|
||||
updateUsage(EffectiveFormat::Alpha16F , LOCAL_GL_ALPHA , LOCAL_GL_HALF_FLOAT_OES);
|
||||
}
|
||||
|
||||
WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl)
|
||||
{
|
||||
gl::GLContext* gl = webgl->GL();
|
||||
|
||||
if (!gl->IsSupported(gl::GLFeature::texture_half_float) &&
|
||||
!gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool needSizedInternal = !gl->IsGLES();
|
||||
const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
|
||||
|
||||
if (needSizedInternal && !hasSwizzle)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat, OES_texture_half_float)
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -10,16 +10,32 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using mozilla::webgl::EffectiveFormat;
|
||||
|
||||
WebGLExtensionTextureHalfFloatLinear::WebGLExtensionTextureHalfFloatLinear(WebGLContext* webgl)
|
||||
: WebGLExtensionBase(webgl)
|
||||
{
|
||||
auto& fua = webgl->mFormatUsage;
|
||||
// This update requires that the authority already be populated by
|
||||
// WebGLExtensionTextureHalfFloat. Enabling extensions to control
|
||||
// features is a mess in WebGL
|
||||
|
||||
fua->EditUsage(webgl::EffectiveFormat::RGBA16F)->isFilterable = true;
|
||||
fua->EditUsage(webgl::EffectiveFormat::RGB16F)->isFilterable = true;
|
||||
fua->EditUsage(webgl::EffectiveFormat::Luminance16FAlpha16F)->isFilterable = true;
|
||||
fua->EditUsage(webgl::EffectiveFormat::Luminance16F)->isFilterable = true;
|
||||
fua->EditUsage(webgl::EffectiveFormat::Alpha16F)->isFilterable = true;
|
||||
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
|
||||
|
||||
auto updateUsage = [authority](EffectiveFormat effectiveFormat) {
|
||||
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
|
||||
MOZ_ASSERT(usage);
|
||||
usage->isFilterable = true;
|
||||
};
|
||||
|
||||
// Ensure require formats are initialized.
|
||||
WebGLExtensionTextureHalfFloat::InitWebGLFormats(authority);
|
||||
|
||||
// Update usage to allow isFilterable
|
||||
updateUsage(EffectiveFormat::RGBA16F);
|
||||
updateUsage(EffectiveFormat::RGB16F);
|
||||
updateUsage(EffectiveFormat::Luminance16FAlpha16F);
|
||||
updateUsage(EffectiveFormat::Luminance16F);
|
||||
updateUsage(EffectiveFormat::Alpha16F);
|
||||
}
|
||||
|
||||
WebGLExtensionTextureHalfFloatLinear::~WebGLExtensionTextureHalfFloatLinear()
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
explicit WebGLExtensionBase(WebGLContext* webgl);
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
void MarkLost();
|
||||
@ -219,8 +219,6 @@ public:
|
||||
explicit WebGLExtensionTextureFloat(WebGLContext*);
|
||||
virtual ~WebGLExtensionTextureFloat();
|
||||
|
||||
static bool IsSupported(const WebGLContext*);
|
||||
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
@ -243,8 +241,6 @@ public:
|
||||
explicit WebGLExtensionTextureHalfFloat(WebGLContext*);
|
||||
virtual ~WebGLExtensionTextureHalfFloat();
|
||||
|
||||
static bool IsSupported(const WebGLContext*);
|
||||
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
@ -293,6 +289,14 @@ public:
|
||||
|
||||
static bool IsSupported(const WebGLContext*);
|
||||
|
||||
static const size_t kMinColorAttachments = 4;
|
||||
static const size_t kMinDrawBuffers = 4;
|
||||
/*
|
||||
WEBGL_draw_buffers does not give a minal value for GL_MAX_DRAW_BUFFERS. But, we request
|
||||
for GL_MAX_DRAW_BUFFERS = 4 at least to be able to use all requested color attachments.
|
||||
See DrawBuffersWEBGL in WebGLExtensionDrawBuffers.cpp inner comments for more informations.
|
||||
*/
|
||||
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -93,7 +93,10 @@ enum class EffectiveFormat : EffectiveFormatValueT {
|
||||
// GLES 3.0.4, p205-206, "Required Renderbuffer Formats"
|
||||
STENCIL_INDEX8,
|
||||
|
||||
////////////////////////////////////
|
||||
// GLES 3.0.4, p128, table 3.12.
|
||||
Luminance8Alpha8,
|
||||
Luminance8,
|
||||
Alpha8,
|
||||
|
||||
// GLES 3.0.4, p147, table 3.19
|
||||
// GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
|
||||
@ -114,10 +117,10 @@ enum class EffectiveFormat : EffectiveFormatValueT {
|
||||
ATC_RGBA_INTERPOLATED_ALPHA_AMD,
|
||||
|
||||
// EXT_texture_compression_s3tc
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT3_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT5_EXT,
|
||||
COMPRESSED_RGB_S3TC_DXT1,
|
||||
COMPRESSED_RGBA_S3TC_DXT1,
|
||||
COMPRESSED_RGBA_S3TC_DXT3,
|
||||
COMPRESSED_RGBA_S3TC_DXT5,
|
||||
|
||||
// IMG_texture_compression_pvrtc
|
||||
COMPRESSED_RGB_PVRTC_4BPPV1,
|
||||
@ -126,14 +129,7 @@ enum class EffectiveFormat : EffectiveFormatValueT {
|
||||
COMPRESSED_RGBA_PVRTC_2BPPV1,
|
||||
|
||||
// OES_compressed_ETC1_RGB8_texture
|
||||
ETC1_RGB8_OES,
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
// GLES 3.0.4, p128, table 3.12.
|
||||
Luminance8Alpha8,
|
||||
Luminance8,
|
||||
Alpha8,
|
||||
ETC1_RGB8,
|
||||
|
||||
// OES_texture_float
|
||||
Luminance32FAlpha32F,
|
||||
@ -161,151 +157,116 @@ enum class UnsizedFormat : uint8_t {
|
||||
DS,
|
||||
};
|
||||
|
||||
// GLES 3.0.4 p114 Table 3.4, p240
|
||||
// GLES 3.0.4 p114 Table 3.4
|
||||
enum class ComponentType : uint8_t {
|
||||
None,
|
||||
None, // DEPTH_COMPONENT32F
|
||||
Int, // RGBA32I
|
||||
UInt, // RGBA32UI, STENCIL_INDEX8
|
||||
UInt, // RGBA32UI
|
||||
NormInt, // RGBA8_SNORM
|
||||
NormUInt, // RGBA8, DEPTH_COMPONENT16
|
||||
NormUInt, // RGBA8
|
||||
NormUIntSRGB, // SRGB8_ALPHA8
|
||||
Float, // RGBA32F
|
||||
Special, // DEPTH24_STENCIL8
|
||||
SharedExp, // RGB9_E5
|
||||
};
|
||||
|
||||
enum class CompressionFamily : uint8_t {
|
||||
ETC1,
|
||||
ES3, // ETC2 or EAC
|
||||
ATC,
|
||||
S3TC,
|
||||
PVRTC,
|
||||
enum class SubImageUpdateBehavior : uint8_t {
|
||||
Forbidden,
|
||||
FullOnly,
|
||||
BlockAligned,
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CompressedFormatInfo
|
||||
{
|
||||
struct CompressedFormatInfo {
|
||||
const EffectiveFormat effectiveFormat;
|
||||
const uint8_t bytesPerBlock;
|
||||
const uint8_t blockWidth;
|
||||
const uint8_t blockHeight;
|
||||
const CompressionFamily family;
|
||||
const bool requirePOT;
|
||||
const SubImageUpdateBehavior subImageUpdateBehavior;
|
||||
};
|
||||
|
||||
struct FormatInfo
|
||||
{
|
||||
struct FormatInfo {
|
||||
const EffectiveFormat effectiveFormat;
|
||||
const char* const name;
|
||||
const GLenum sizedFormat;
|
||||
const UnsizedFormat unsizedFormat;
|
||||
const ComponentType componentType;
|
||||
const uint8_t estimatedBytesPerPixel; // 0 iff `!!compression`. Only use this for
|
||||
const bool isColorFormat; // memory usage estimation. Use
|
||||
const bool isSRGB; // BytesPerPixel(packingFormat, packingType) for
|
||||
const bool hasAlpha; // calculating pack/unpack byte count.
|
||||
const ComponentType colorComponentType;
|
||||
const uint8_t bytesPerPixel; // 0 iff `!!compression`.
|
||||
const bool hasColor;
|
||||
const bool hasAlpha;
|
||||
const bool hasDepth;
|
||||
const bool hasStencil;
|
||||
|
||||
const CompressedFormatInfo* const compression;
|
||||
};
|
||||
|
||||
struct PackingInfo
|
||||
{
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
|
||||
bool operator <(const PackingInfo& x) const
|
||||
{
|
||||
if (format != x.format)
|
||||
return format < x.format;
|
||||
|
||||
return type < x.type;
|
||||
}
|
||||
};
|
||||
|
||||
struct DriverUnpackInfo
|
||||
{
|
||||
GLenum internalFormat;
|
||||
GLenum unpackFormat;
|
||||
GLenum unpackType;
|
||||
|
||||
PackingInfo ToPacking() const {
|
||||
return {unpackFormat, unpackType};
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const FormatInfo* GetFormat(EffectiveFormat format);
|
||||
uint8_t BytesPerPixel(const PackingInfo& packing);
|
||||
/*
|
||||
GLint ComponentSize(const FormatInfo* format, GLenum component);
|
||||
GLenum ComponentType(const FormatInfo* format);
|
||||
*/
|
||||
const FormatInfo* GetFormatInfo(EffectiveFormat format);
|
||||
const FormatInfo* GetInfoByUnpackTuple(GLenum unpackFormat, GLenum unpackType);
|
||||
const FormatInfo* GetInfoBySizedFormat(GLenum sizedFormat);
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
struct FormatUsageInfo
|
||||
{
|
||||
const FormatInfo* const format;
|
||||
struct UnpackTuple {
|
||||
const GLenum format;
|
||||
const GLenum type;
|
||||
|
||||
bool operator <(const UnpackTuple& x) const
|
||||
{
|
||||
if (format == x.format) {
|
||||
return type < x.type;
|
||||
}
|
||||
|
||||
return format < x.format;
|
||||
}
|
||||
};
|
||||
|
||||
struct FormatUsageInfo {
|
||||
const FormatInfo* const formatInfo;
|
||||
bool asRenderbuffer;
|
||||
bool isRenderable;
|
||||
bool asTexture;
|
||||
bool isFilterable;
|
||||
std::map<PackingInfo, DriverUnpackInfo> validUnpacks;
|
||||
const DriverUnpackInfo* idealUnpack;
|
||||
const GLint* textureSwizzleRGBA;
|
||||
std::set<UnpackTuple> validUnpacks;
|
||||
|
||||
static const GLint kLuminanceSwizzleRGBA[4];
|
||||
static const GLint kAlphaSwizzleRGBA[4];
|
||||
static const GLint kLumAlphaSwizzleRGBA[4];
|
||||
|
||||
explicit FormatUsageInfo(const FormatInfo* _format)
|
||||
: format(_format)
|
||||
, isRenderable(false)
|
||||
, isFilterable(false)
|
||||
, idealUnpack(nullptr)
|
||||
, textureSwizzleRGBA(nullptr)
|
||||
{ }
|
||||
|
||||
bool IsUnpackValid(const PackingInfo& key,
|
||||
const DriverUnpackInfo** const out_value) const;
|
||||
bool CanUnpackWith(GLenum unpackFormat, GLenum unpackType) const;
|
||||
};
|
||||
|
||||
class FormatUsageAuthority
|
||||
{
|
||||
std::map<EffectiveFormat, FormatUsageInfo> mUsageMap;
|
||||
|
||||
std::map<GLenum, const FormatUsageInfo*> mRBFormatMap;
|
||||
std::map<GLenum, const FormatUsageInfo*> mSizedTexFormatMap;
|
||||
std::map<PackingInfo, const FormatUsageInfo*> mUnsizedTexFormatMap;
|
||||
|
||||
std::set<GLenum> mValidTexInternalFormats;
|
||||
std::set<GLenum> mValidTexUnpackFormats;
|
||||
std::set<GLenum> mValidTexUnpackTypes;
|
||||
std::map<EffectiveFormat, FormatUsageInfo> mInfoMap;
|
||||
|
||||
public:
|
||||
static UniquePtr<FormatUsageAuthority> CreateForWebGL1(gl::GLContext* gl);
|
||||
static UniquePtr<FormatUsageAuthority> CreateForWebGL2(gl::GLContext* gl);
|
||||
static UniquePtr<FormatUsageAuthority> CreateForWebGL1();
|
||||
static UniquePtr<FormatUsageAuthority> CreateForWebGL2();
|
||||
|
||||
private:
|
||||
FormatUsageAuthority() { }
|
||||
|
||||
public:
|
||||
FormatUsageInfo* EditUsage(EffectiveFormat format);
|
||||
const FormatUsageInfo* GetUsage(EffectiveFormat format) const;
|
||||
void AddFormat(EffectiveFormat format, bool asRenderbuffer, bool isRenderable,
|
||||
bool asTexture, bool isFilterable);
|
||||
|
||||
void AddTexUnpack(FormatUsageInfo* usage, const PackingInfo& pi,
|
||||
const DriverUnpackInfo& dui);
|
||||
void AddUnpackOption(GLenum unpackFormat, GLenum unpackType,
|
||||
EffectiveFormat effectiveFormat);
|
||||
|
||||
bool IsInternalFormatEnumValid(GLenum internalFormat) const;
|
||||
bool AreUnpackEnumsValid(GLenum unpackFormat, GLenum unpackType) const;
|
||||
FormatUsageInfo* GetUsage(EffectiveFormat format);
|
||||
FormatUsageInfo* GetUsage(const FormatInfo* format)
|
||||
{
|
||||
if (!format)
|
||||
return nullptr;
|
||||
|
||||
void AllowRBFormat(GLenum sizedFormat, const FormatUsageInfo* usage);
|
||||
void AllowSizedTexFormat(GLenum sizedFormat, const FormatUsageInfo* usage);
|
||||
void AllowUnsizedTexFormat(const PackingInfo& pi, const FormatUsageInfo* usage);
|
||||
|
||||
const FormatUsageInfo* GetRBUsage(GLenum sizedFormat) const;
|
||||
const FormatUsageInfo* GetSizedTexUsage(GLenum sizedFormat) const;
|
||||
const FormatUsageInfo* GetUnsizedTexUsage(const PackingInfo& pi) const;
|
||||
return GetUsage(format->effectiveFormat);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLint GetComponentSize(EffectiveFormat format, GLenum component);
|
||||
GLenum GetComponentType(EffectiveFormat format);
|
||||
GLenum GetColorEncoding(EffectiveFormat format);
|
||||
|
||||
} // namespace webgl
|
||||
} // namespace mozilla
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,9 +21,6 @@ class WebGLFramebuffer;
|
||||
class WebGLRenderbuffer;
|
||||
class WebGLTexture;
|
||||
|
||||
template<typename T>
|
||||
class PlacementArray;
|
||||
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
} // namespace gl
|
||||
@ -32,39 +29,34 @@ class WebGLFBAttachPoint
|
||||
{
|
||||
public:
|
||||
WebGLFramebuffer* const mFB;
|
||||
const GLenum mAttachmentPoint;
|
||||
private:
|
||||
WebGLRefPtr<WebGLTexture> mTexturePtr;
|
||||
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
|
||||
FBAttachment mAttachmentPoint;
|
||||
TexImageTarget mTexImageTarget;
|
||||
GLint mTexImageLayer;
|
||||
GLint mTexImageLevel;
|
||||
|
||||
// PlacementArray needs a default constructor.
|
||||
template<typename T>
|
||||
friend class PlacementArray;
|
||||
|
||||
WebGLFBAttachPoint()
|
||||
: mFB(nullptr)
|
||||
, mAttachmentPoint(0)
|
||||
{ }
|
||||
|
||||
|
||||
public:
|
||||
WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint);
|
||||
WebGLFBAttachPoint(WebGLFramebuffer* fb, FBAttachment attachmentPoint);
|
||||
~WebGLFBAttachPoint();
|
||||
|
||||
void Unlink();
|
||||
void Unlink() {
|
||||
mRenderbufferPtr = nullptr;
|
||||
mTexturePtr = nullptr;
|
||||
}
|
||||
|
||||
bool IsDefined() const;
|
||||
bool IsDeleteRequested() const;
|
||||
|
||||
const webgl::FormatUsageInfo* Format() const;
|
||||
TexInternalFormat EffectiveInternalFormat() const;
|
||||
|
||||
bool HasAlpha() const;
|
||||
bool IsReadableFloat() const;
|
||||
|
||||
void Clear();
|
||||
void Clear() {
|
||||
SetRenderbuffer(nullptr);
|
||||
}
|
||||
|
||||
void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level);
|
||||
void SetTexImageLayer(WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
@ -96,68 +88,15 @@ public:
|
||||
bool HasUninitializedImageData() const;
|
||||
void SetImageDataStatus(WebGLImageDataStatus x);
|
||||
|
||||
void Size(uint32_t* const out_width, uint32_t* const out_height) const;
|
||||
//const WebGLRectangleObject& RectangleObject() const;
|
||||
const WebGLRectangleObject& RectangleObject() const;
|
||||
|
||||
bool HasImage() const;
|
||||
bool IsComplete(WebGLContext* webgl) const;
|
||||
bool IsComplete() const;
|
||||
|
||||
void FinalizeAttachment(gl::GLContext* gl, GLenum attachmentLoc) const;
|
||||
void FinalizeAttachment(gl::GLContext* gl,
|
||||
FBAttachment attachmentLoc) const;
|
||||
|
||||
JS::Value GetParameter(const char* funcName, WebGLContext* webgl, JSContext* cx,
|
||||
GLenum target, GLenum attachment, GLenum pname,
|
||||
ErrorResult* const out_error);
|
||||
|
||||
void OnBackingStoreRespecified() const;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class PlacementArray
|
||||
{
|
||||
public:
|
||||
const size_t mCapacity;
|
||||
protected:
|
||||
size_t mSize;
|
||||
T* const mArray;
|
||||
|
||||
public:
|
||||
explicit PlacementArray(size_t capacity)
|
||||
: mCapacity(capacity)
|
||||
, mSize(0)
|
||||
, mArray((T*)moz_xmalloc(sizeof(T) * capacity))
|
||||
{ }
|
||||
|
||||
~PlacementArray() {
|
||||
for (auto& cur : *this) {
|
||||
cur.~T();
|
||||
}
|
||||
free(mArray);
|
||||
}
|
||||
|
||||
T* begin() const {
|
||||
return mArray;
|
||||
}
|
||||
|
||||
T* end() const {
|
||||
return mArray + mSize;
|
||||
}
|
||||
|
||||
T& operator [](size_t offset) const {
|
||||
MOZ_ASSERT(offset < mSize);
|
||||
return mArray[offset];
|
||||
}
|
||||
|
||||
const size_t& Size() const { return mSize; }
|
||||
|
||||
template<typename A, typename B>
|
||||
void AppendNew(A a, B b) {
|
||||
if (mSize == mCapacity)
|
||||
MOZ_CRASH("Bad EmplaceAppend.");
|
||||
|
||||
// Placement `new`:
|
||||
new (&(mArray[mSize])) T(a, b);
|
||||
++mSize;
|
||||
}
|
||||
JS::Value GetParameter(WebGLContext* context, GLenum pname);
|
||||
};
|
||||
|
||||
class WebGLFramebuffer final
|
||||
@ -175,7 +114,7 @@ public:
|
||||
const GLuint mGLName;
|
||||
|
||||
private:
|
||||
mutable bool mIsKnownFBComplete;
|
||||
mutable GLenum mStatus;
|
||||
|
||||
GLenum mReadBufferMode;
|
||||
|
||||
@ -184,17 +123,7 @@ private:
|
||||
WebGLFBAttachPoint mDepthAttachment;
|
||||
WebGLFBAttachPoint mStencilAttachment;
|
||||
WebGLFBAttachPoint mDepthStencilAttachment;
|
||||
|
||||
PlacementArray<WebGLFBAttachPoint> mMoreColorAttachments;
|
||||
|
||||
std::vector<GLenum> mDrawBuffers;
|
||||
|
||||
bool IsDrawBuffer(size_t n) const {
|
||||
if (n < mDrawBuffers.size())
|
||||
return bool(mDrawBuffers[n]);
|
||||
|
||||
return false;
|
||||
}
|
||||
nsTArray<WebGLFBAttachPoint> mMoreColorAttachments;
|
||||
|
||||
#ifdef ANDROID
|
||||
// Bug 1140459: Some drivers (including our test slaves!) don't
|
||||
@ -218,11 +147,14 @@ private:
|
||||
public:
|
||||
void Delete();
|
||||
|
||||
void FramebufferRenderbuffer(GLenum attachment, RBTarget rbtarget,
|
||||
void FramebufferRenderbuffer(FBAttachment attachment, RBTarget rbtarget,
|
||||
WebGLRenderbuffer* rb);
|
||||
void FramebufferTexture2D(GLenum attachment, TexImageTarget texImageTarget,
|
||||
WebGLTexture* tex, GLint level);
|
||||
void FramebufferTextureLayer(GLenum attachment, WebGLTexture* tex, GLint level,
|
||||
|
||||
void FramebufferTexture2D(FBAttachment attachment,
|
||||
TexImageTarget texImageTarget, WebGLTexture* tex,
|
||||
GLint level);
|
||||
|
||||
void FramebufferTextureLayer(FBAttachment attachment, WebGLTexture* tex, GLint level,
|
||||
GLint layer);
|
||||
|
||||
bool HasDefinedAttachments() const;
|
||||
@ -231,11 +163,20 @@ public:
|
||||
FBStatus PrecheckFramebufferStatus() const;
|
||||
FBStatus CheckFramebufferStatus() const;
|
||||
|
||||
const webgl::FormatUsageInfo*
|
||||
GLenum
|
||||
GetFormatForAttachment(const WebGLFBAttachPoint& attachment) const;
|
||||
|
||||
bool HasDepthStencilConflict() const {
|
||||
return int(mDepthAttachment.IsDefined()) +
|
||||
int(mStencilAttachment.IsDefined()) +
|
||||
int(mDepthStencilAttachment.IsDefined()) >= 2;
|
||||
}
|
||||
|
||||
size_t ColorAttachmentCount() const {
|
||||
return 1 + mMoreColorAttachments.Length();
|
||||
}
|
||||
const WebGLFBAttachPoint& ColorAttachment(size_t colorAttachmentId) const {
|
||||
MOZ_ASSERT(colorAttachmentId < 1 + mMoreColorAttachments.Size());
|
||||
MOZ_ASSERT(colorAttachmentId < ColorAttachmentCount());
|
||||
return colorAttachmentId ? mMoreColorAttachments[colorAttachmentId - 1]
|
||||
: mColorAttachment0;
|
||||
}
|
||||
@ -252,16 +193,16 @@ public:
|
||||
return mDepthStencilAttachment;
|
||||
}
|
||||
|
||||
protected:
|
||||
WebGLFBAttachPoint* GetAttachPoint(GLenum attachment); // Fallible
|
||||
WebGLFBAttachPoint& GetAttachPoint(FBAttachment attachPointEnum);
|
||||
|
||||
public:
|
||||
void DetachTexture(const WebGLTexture* tex);
|
||||
|
||||
void DetachRenderbuffer(const WebGLRenderbuffer* rb);
|
||||
|
||||
const WebGLRectangleObject& RectangleObject() const;
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
void FinalizeAttachments() const;
|
||||
@ -276,17 +217,19 @@ public:
|
||||
|
||||
bool CheckAndInitializeAttachments();
|
||||
|
||||
bool CheckColorAttachmentNumber(FBAttachment attachment,
|
||||
const char* funcName) const;
|
||||
|
||||
void EnsureColorAttachPoints(size_t colorAttachmentId);
|
||||
|
||||
void InvalidateFramebufferStatus() const {
|
||||
mIsKnownFBComplete = false;
|
||||
mStatus = 0;
|
||||
}
|
||||
|
||||
bool ValidateForRead(const char* info,
|
||||
const webgl::FormatUsageInfo** const out_format,
|
||||
uint32_t* const out_width, uint32_t* const out_height);
|
||||
bool ValidateForRead(const char* info, TexInternalFormat* const out_format);
|
||||
|
||||
JS::Value GetAttachmentParameter(const char* funcName, JSContext* cx, GLenum target,
|
||||
GLenum attachment, GLenum pname,
|
||||
ErrorResult* const out_error);
|
||||
JS::Value GetAttachmentParameter(JSContext* cx, GLenum attachment, GLenum pname,
|
||||
ErrorResult& rv);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -269,8 +269,10 @@ public:
|
||||
|
||||
bool IsCompatibleWithContext(WebGLContext* other);
|
||||
|
||||
WebGLContext* const mContext;
|
||||
WebGLContext* Context() const { return mContext; }
|
||||
|
||||
protected:
|
||||
WebGLContext* const mContext;
|
||||
const uint32_t mContextGeneration;
|
||||
};
|
||||
|
||||
|
@ -167,7 +167,7 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
|
||||
#endif
|
||||
|
||||
const bool isArray = false;
|
||||
AddActiveInfo(prog->mContext, elemCount, elemType, isArray, userName, mappedName,
|
||||
AddActiveInfo(prog->Context(), elemCount, elemType, isArray, userName, mappedName,
|
||||
&info->activeAttribs, &info->attribMap);
|
||||
|
||||
// Collect active locations:
|
||||
@ -232,7 +232,7 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
|
||||
printf_stderr(" isArray: %d\n", (int)isArray);
|
||||
#endif
|
||||
|
||||
AddActiveInfo(prog->mContext, elemCount, elemType, isArray, baseUserName,
|
||||
AddActiveInfo(prog->Context(), elemCount, elemType, isArray, baseUserName,
|
||||
baseMappedName, &info->activeUniforms, &info->uniformMap);
|
||||
}
|
||||
|
||||
@ -327,9 +327,8 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
|
||||
}
|
||||
}
|
||||
|
||||
AddActiveInfo(prog->mContext, size, type, isArray, baseUserName, mappedName,
|
||||
&info->transformFeedbackVaryings,
|
||||
&info->transformFeedbackVaryingsMap);
|
||||
AddActiveInfo(prog->Context(), size, type, isArray, baseUserName, mappedName,
|
||||
&info->transformFeedbackVaryings, &info->transformFeedbackVaryingsMap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,6 +337,7 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
webgl::LinkedProgramInfo::LinkedProgramInfo(WebGLProgram* prog)
|
||||
: prog(prog)
|
||||
, fragDataMap(nullptr)
|
||||
|
@ -196,7 +196,7 @@ public:
|
||||
}
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto) override;
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
|
||||
// nsWrapperCache
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
// NS
|
||||
|
@ -51,10 +51,10 @@ WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* webgl)
|
||||
: WebGLContextBoundObject(webgl)
|
||||
, mPrimaryRB(0)
|
||||
, mSecondaryRB(0)
|
||||
, mFormat(nullptr)
|
||||
, mInternalFormat(0)
|
||||
, mInternalFormatForGL(0)
|
||||
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
|
||||
, mSamples(1)
|
||||
, mIsUsingSecondary(false)
|
||||
#ifdef ANDROID
|
||||
, mIsRB(false)
|
||||
#endif
|
||||
@ -86,21 +86,62 @@ WebGLRenderbuffer::Delete()
|
||||
int64_t
|
||||
WebGLRenderbuffer::MemoryUsage() const
|
||||
{
|
||||
int64_t pixels = int64_t(Width()) * int64_t(Height());
|
||||
|
||||
GLenum primaryFormat = InternalFormatForGL();
|
||||
// If there is no defined format, we're not taking up any memory
|
||||
if (!mFormat)
|
||||
if (!primaryFormat)
|
||||
return 0;
|
||||
|
||||
auto bytesPerPixel = mFormat->format->estimatedBytesPerPixel;
|
||||
uint64_t pixels = uint64_t(mWidth) * uint64_t(mHeight);
|
||||
|
||||
uint64_t totalSize = pixels * bytesPerPixel;
|
||||
|
||||
// If we have the same bytesPerPixel whether or not we have a secondary RB.
|
||||
if (mSecondaryRB && !mIsUsingSecondary) {
|
||||
totalSize += 2; // 1x1xRGBA4
|
||||
int64_t secondarySize = 0;
|
||||
if (mSecondaryRB) {
|
||||
if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
|
||||
primaryFormat = DepthStencilDepthFormat(mContext->gl);
|
||||
secondarySize = 1*pixels; // STENCIL_INDEX8
|
||||
} else {
|
||||
secondarySize = 1*1*2; // 1x1xRGBA4
|
||||
}
|
||||
}
|
||||
|
||||
return int64_t(totalSize);
|
||||
int64_t primarySize = 0;
|
||||
switch (primaryFormat) {
|
||||
case LOCAL_GL_STENCIL_INDEX8:
|
||||
primarySize = 1*pixels;
|
||||
break;
|
||||
case LOCAL_GL_RGBA4:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
case LOCAL_GL_RGB565:
|
||||
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||
primarySize = 2*pixels;
|
||||
break;
|
||||
case LOCAL_GL_RGB8:
|
||||
case LOCAL_GL_DEPTH_COMPONENT24:
|
||||
primarySize = 3*pixels;
|
||||
break;
|
||||
case LOCAL_GL_RGBA8:
|
||||
case LOCAL_GL_SRGB8_ALPHA8_EXT:
|
||||
case LOCAL_GL_DEPTH24_STENCIL8:
|
||||
case LOCAL_GL_DEPTH_COMPONENT32:
|
||||
primarySize = 4*pixels;
|
||||
break;
|
||||
case LOCAL_GL_RGB16F:
|
||||
primarySize = 2*3*pixels;
|
||||
break;
|
||||
case LOCAL_GL_RGBA16F:
|
||||
primarySize = 2*4*pixels;
|
||||
break;
|
||||
case LOCAL_GL_RGB32F:
|
||||
primarySize = 4*3*pixels;
|
||||
break;
|
||||
case LOCAL_GL_RGBA32F:
|
||||
primarySize = 4*4*pixels;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unknown `primaryFormat`.");
|
||||
break;
|
||||
}
|
||||
|
||||
return primarySize + secondarySize;
|
||||
}
|
||||
|
||||
void
|
||||
@ -131,60 +172,27 @@ RenderbufferStorageMaybeMultisample(gl::GLContext* gl, GLsizei samples,
|
||||
MOZ_ASSERT(samples >= 0);
|
||||
MOZ_ASSERT(samples <= gl->MaxSamples());
|
||||
|
||||
// certain OpenGL ES renderbuffer formats may not exist on desktop OpenGL
|
||||
GLenum internalFormatForGL = internalFormat;
|
||||
|
||||
switch (internalFormat) {
|
||||
case LOCAL_GL_RGBA4:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
// 16-bit RGBA formats are not supported on desktop GL
|
||||
if (!gl->IsGLES())
|
||||
internalFormatForGL = LOCAL_GL_RGBA8;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_RGB565:
|
||||
// the RGB565 format is not supported on desktop GL
|
||||
if (!gl->IsGLES())
|
||||
internalFormatForGL = LOCAL_GL_RGB8;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||
if (!gl->IsGLES() || gl->IsExtensionSupported(gl::GLContext::OES_depth24))
|
||||
internalFormatForGL = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
else if (gl->IsExtensionSupported(gl::GLContext::OES_packed_depth_stencil))
|
||||
internalFormatForGL = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_DEPTH_STENCIL:
|
||||
// We emulate this in WebGLRenderbuffer if we don't have the requisite extension.
|
||||
internalFormatForGL = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (samples > 0) {
|
||||
gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples,
|
||||
internalFormatForGL, width, height);
|
||||
internalFormat, width, height);
|
||||
} else {
|
||||
gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, internalFormatForGL, width,
|
||||
gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, internalFormat, width,
|
||||
height);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLRenderbuffer::RenderbufferStorage(GLsizei samples,
|
||||
const webgl::FormatUsageInfo* format,
|
||||
GLsizei width, GLsizei height)
|
||||
WebGLRenderbuffer::RenderbufferStorage(GLsizei samples, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height) const
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundRenderbuffer == this);
|
||||
|
||||
InvalidateStatusOfAttachedFBs();
|
||||
|
||||
gl::GLContext* gl = mContext->gl;
|
||||
MOZ_ASSERT(samples >= 0 && samples <= 256); // Sanity check.
|
||||
|
||||
GLenum primaryFormat = format->format->sizedFormat;
|
||||
GLenum primaryFormat = internalFormat;
|
||||
GLenum secondaryFormat = 0;
|
||||
|
||||
if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
|
||||
@ -195,42 +203,35 @@ WebGLRenderbuffer::RenderbufferStorage(GLsizei samples,
|
||||
RenderbufferStorageMaybeMultisample(gl, samples, primaryFormat, width,
|
||||
height);
|
||||
|
||||
if (mSecondaryRB) {
|
||||
// We can't leave the secondary RB unspecified either, since we should
|
||||
// handle the case where we attach a non-depth-stencil RB to a
|
||||
// depth-stencil attachment point, or attach this depth-stencil RB to a
|
||||
// non-depth-stencil attachment point.
|
||||
gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
|
||||
if (secondaryFormat) {
|
||||
RenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat, width,
|
||||
height);
|
||||
} else {
|
||||
RenderbufferStorageMaybeMultisample(gl, samples, LOCAL_GL_RGBA4, 1, 1);
|
||||
}
|
||||
if (!mSecondaryRB) {
|
||||
MOZ_ASSERT(!secondaryFormat);
|
||||
return;
|
||||
}
|
||||
// We can't leave the secondary RB unspecified either, since we should
|
||||
// handle the case where we attach a non-depth-stencil RB to a
|
||||
// depth-stencil attachment point, or attach this depth-stencil RB to a
|
||||
// non-depth-stencil attachment point.
|
||||
gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
|
||||
if (secondaryFormat) {
|
||||
RenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat, width,
|
||||
height);
|
||||
} else {
|
||||
RenderbufferStorageMaybeMultisample(gl, samples, LOCAL_GL_RGBA4, 1, 1);
|
||||
}
|
||||
|
||||
mSamples = samples;
|
||||
mFormat = format;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mImageDataStatus = WebGLImageDataStatus::UninitializedImageData;
|
||||
mIsUsingSecondary = bool(secondaryFormat);
|
||||
|
||||
InvalidateStatusOfAttachedFBs();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLRenderbuffer::FramebufferRenderbuffer(GLenum attachment) const
|
||||
WebGLRenderbuffer::FramebufferRenderbuffer(FBAttachment attachment) const
|
||||
{
|
||||
gl::GLContext* gl = mContext->gl;
|
||||
if (attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment,
|
||||
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment.get(),
|
||||
LOCAL_GL_RENDERBUFFER, mPrimaryRB);
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint stencilRB = mPrimaryRB;
|
||||
if (mIsUsingSecondary) {
|
||||
if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
|
||||
MOZ_ASSERT(mSecondaryRB);
|
||||
stencilRB = mSecondaryRB;
|
||||
}
|
||||
@ -250,13 +251,20 @@ WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
|
||||
|
||||
switch (pname.get()) {
|
||||
case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
|
||||
if (!mFormat)
|
||||
return 0;
|
||||
if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
|
||||
if (gl->WorkAroundDriverBugs() &&
|
||||
gl->Renderer() == gl::GLRenderer::Tegra)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
if (!mFormat->format->hasStencil)
|
||||
return 0;
|
||||
gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
|
||||
|
||||
return 8;
|
||||
GLint i = 0;
|
||||
gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
|
||||
return i;
|
||||
}
|
||||
// Fall through otherwise.
|
||||
|
||||
case LOCAL_GL_RENDERBUFFER_WIDTH:
|
||||
case LOCAL_GL_RENDERBUFFER_HEIGHT:
|
||||
@ -270,19 +278,6 @@ WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
|
||||
gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
|
||||
{
|
||||
GLenum ret = 0;
|
||||
if (mFormat) {
|
||||
ret = mFormat->format->sizedFormat;
|
||||
|
||||
if (!mContext->IsWebGL2() && ret == LOCAL_GL_DEPTH24_STENCIL8) {
|
||||
ret = LOCAL_GL_DEPTH_STENCIL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false,
|
||||
|
@ -14,9 +14,6 @@
|
||||
#include "WebGLStrongTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgl {
|
||||
struct FormatUsageInfo;
|
||||
}
|
||||
|
||||
class WebGLRenderbuffer final
|
||||
: public nsWrapperCache
|
||||
@ -32,34 +29,40 @@ public:
|
||||
void Delete();
|
||||
|
||||
bool HasUninitializedImageData() const {
|
||||
MOZ_ASSERT(mImageDataStatus != WebGLImageDataStatus::NoImageData);
|
||||
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
|
||||
}
|
||||
|
||||
bool IsDefined() const {
|
||||
if (!mFormat) {
|
||||
MOZ_ASSERT(!mWidth && !mHeight);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
void SetImageDataStatus(WebGLImageDataStatus x) {
|
||||
// there is no way to go from having image data to not having any
|
||||
MOZ_ASSERT(x != WebGLImageDataStatus::NoImageData ||
|
||||
mImageDataStatus == WebGLImageDataStatus::NoImageData);
|
||||
mImageDataStatus = x;
|
||||
}
|
||||
|
||||
GLsizei Samples() const { return mSamples; }
|
||||
void SetSamples(GLsizei samples) { mSamples = samples; }
|
||||
|
||||
GLuint PrimaryGLName() const { return mPrimaryRB; }
|
||||
|
||||
const webgl::FormatUsageInfo* Format() const { return mFormat; }
|
||||
GLenum InternalFormat() const { return mInternalFormat; }
|
||||
void SetInternalFormat(GLenum internalFormat) {
|
||||
mInternalFormat = internalFormat;
|
||||
}
|
||||
|
||||
GLenum InternalFormatForGL() const { return mInternalFormatForGL; }
|
||||
void SetInternalFormatForGL(GLenum internalFormatForGL) {
|
||||
mInternalFormatForGL = internalFormatForGL;
|
||||
}
|
||||
|
||||
int64_t MemoryUsage() const;
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
void BindRenderbuffer() const;
|
||||
void RenderbufferStorage(GLsizei samples, const webgl::FormatUsageInfo* format,
|
||||
GLsizei width, GLsizei height);
|
||||
void FramebufferRenderbuffer(GLenum attachment) const;
|
||||
void RenderbufferStorage(GLsizei samples, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height) const;
|
||||
void FramebufferRenderbuffer(FBAttachment attachment) const;
|
||||
// Only handles a subset of `pname`s.
|
||||
GLint GetRenderbufferParameter(RBTarget target, RBParam pname) const;
|
||||
|
||||
@ -75,10 +78,10 @@ protected:
|
||||
|
||||
GLuint mPrimaryRB;
|
||||
GLuint mSecondaryRB;
|
||||
const webgl::FormatUsageInfo* mFormat;
|
||||
GLenum mInternalFormat;
|
||||
GLenum mInternalFormatForGL;
|
||||
WebGLImageDataStatus mImageDataStatus;
|
||||
GLsizei mSamples;
|
||||
bool mIsUsingSecondary;
|
||||
#ifdef ANDROID
|
||||
// Bug 1140459: Some drivers (including our test slaves!) don't
|
||||
// give reasonable answers for IsRenderbuffer, maybe others.
|
||||
@ -90,7 +93,6 @@ protected:
|
||||
|
||||
friend class WebGLContext;
|
||||
friend class WebGLFramebuffer;
|
||||
friend class WebGLFBAttachPoint;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -35,7 +35,7 @@ WebGLSampler::Delete()
|
||||
WebGLContext*
|
||||
WebGLSampler::GetParentObject() const
|
||||
{
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsString.h"
|
||||
#include "prenv.h"
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLShaderValidator.h"
|
||||
@ -168,7 +167,7 @@ WebGLShader::ShaderSource(const nsAString& source)
|
||||
|
||||
// We checked that the source stripped of comments is in the
|
||||
// 7-bit ASCII range, so we can skip the NS_IsAscii() check.
|
||||
const NS_LossyConvertUTF16toASCII sourceCString(cleanSource);
|
||||
NS_LossyConvertUTF16toASCII sourceCString(cleanSource);
|
||||
|
||||
if (mContext->gl->WorkAroundDriverBugs()) {
|
||||
const size_t maxSourceLength = 0x3ffff;
|
||||
@ -180,24 +179,23 @@ WebGLShader::ShaderSource(const nsAString& source)
|
||||
}
|
||||
}
|
||||
|
||||
if (PR_GetEnv("MOZ_WEBGL_DUMP_SHADERS")) {
|
||||
printf_stderr("////////////////////////////////////////\n");
|
||||
printf_stderr("// MOZ_WEBGL_DUMP_SHADERS:\n");
|
||||
|
||||
// Wow - Roll Your Own Foreach-Lines because printf_stderr has a hard-coded
|
||||
// internal size, so long strings are truncated.
|
||||
|
||||
// HACK - dump shader source
|
||||
{
|
||||
/*
|
||||
printf_stderr("//-*- glsl -*-\n");
|
||||
// Wow - Roll Your Own For Each Lines because printf_stderr has a hard-coded internal size, so long strings are truncated.
|
||||
const nsString& src = shader->Source();
|
||||
int32_t start = 0;
|
||||
int32_t end = sourceCString.Find("\n", false, start, -1);
|
||||
int32_t end = src.Find("\n", false, start, -1);
|
||||
while (end > -1) {
|
||||
const nsCString line(sourceCString.BeginReading() + start, end - start);
|
||||
printf_stderr("%s\n", line.BeginReading());
|
||||
printf_stderr("%s\n", NS_ConvertUTF16toUTF8(nsDependentSubstring(src, start, end - start)).get());
|
||||
start = end + 1;
|
||||
end = sourceCString.Find("\n", false, start, -1);
|
||||
end = src.Find("\n", false, start, -1);
|
||||
}
|
||||
|
||||
printf_stderr("////////////////////////////////////////\n");
|
||||
printf_stderr("//\n");
|
||||
*/
|
||||
}
|
||||
// HACK
|
||||
|
||||
mSource = source;
|
||||
mCleanSource = sourceCString;
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
void Delete();
|
||||
|
||||
WebGLContext* GetParentObject() const { return mContext; }
|
||||
WebGLContext* GetParentObject() const { return Context(); }
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto) override;
|
||||
|
||||
|
@ -118,16 +118,16 @@ WebGLContext::CreateShaderValidator(GLenum shaderType) const
|
||||
resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
|
||||
resources.MaxDrawBuffers = mGLMaxDrawBuffers;
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
|
||||
if (IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
|
||||
resources.EXT_frag_depth = 1;
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
|
||||
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
|
||||
resources.OES_standard_derivatives = 1;
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
|
||||
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
|
||||
resources.EXT_draw_buffers = 1;
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
|
||||
if (IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
|
||||
resources.EXT_shader_texture_lod = 1;
|
||||
|
||||
// Tell ANGLE to allow highp in frag shaders. (unless disabled)
|
||||
|
@ -223,7 +223,6 @@ STRONG_GLENUM_BEGIN(TexImageTarget)
|
||||
STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_Y),
|
||||
STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_POSITIVE_Z),
|
||||
STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_Z),
|
||||
STRONG_GLENUM_VALUE(TEXTURE_2D_ARRAY),
|
||||
STRONG_GLENUM_END(TexImageTarget)
|
||||
|
||||
STRONG_GLENUM_BEGIN(TexTarget)
|
||||
@ -231,7 +230,6 @@ STRONG_GLENUM_BEGIN(TexTarget)
|
||||
STRONG_GLENUM_VALUE(TEXTURE_2D),
|
||||
STRONG_GLENUM_VALUE(TEXTURE_3D),
|
||||
STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP),
|
||||
STRONG_GLENUM_VALUE(TEXTURE_2D_ARRAY),
|
||||
STRONG_GLENUM_END(TexTarget)
|
||||
|
||||
STRONG_GLENUM_BEGIN(TexType)
|
||||
@ -400,6 +398,28 @@ STRONG_GLENUM_BEGIN(RBTarget)
|
||||
STRONG_GLENUM_VALUE(RENDERBUFFER),
|
||||
STRONG_GLENUM_END(RBTarget)
|
||||
|
||||
STRONG_GLENUM_BEGIN(FBAttachment)
|
||||
STRONG_GLENUM_VALUE(DEPTH_STENCIL_ATTACHMENT),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT0),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT1),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT2),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT3),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT4),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT5),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT6),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT7),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT8),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT9),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT10),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT11),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT12),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT13),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT14),
|
||||
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT15),
|
||||
STRONG_GLENUM_VALUE(DEPTH_ATTACHMENT),
|
||||
STRONG_GLENUM_VALUE(STENCIL_ATTACHMENT),
|
||||
STRONG_GLENUM_END(FBAttachment)
|
||||
|
||||
STRONG_GLENUM_BEGIN(FBStatus)
|
||||
STRONG_GLENUM_VALUE(FRAMEBUFFER_COMPLETE),
|
||||
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
|
||||
@ -413,7 +433,6 @@ STRONG_GLENUM_END(FBStatus)
|
||||
STRONG_GLENUM_BEGIN(RBParam)
|
||||
STRONG_GLENUM_VALUE(RENDERBUFFER_WIDTH),
|
||||
STRONG_GLENUM_VALUE(RENDERBUFFER_HEIGHT),
|
||||
STRONG_GLENUM_VALUE(RENDERBUFFER_INTERNAL_FORMAT),
|
||||
STRONG_GLENUM_VALUE(RENDERBUFFER_RED_SIZE),
|
||||
STRONG_GLENUM_VALUE(RENDERBUFFER_GREEN_SIZE),
|
||||
STRONG_GLENUM_VALUE(RENDERBUFFER_BLUE_SIZE),
|
||||
|
@ -34,7 +34,7 @@ WebGLSync::Delete()
|
||||
WebGLContext*
|
||||
WebGLSync::GetParentObject() const
|
||||
{
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -326,73 +326,73 @@ public:
|
||||
} // end anonymous namespace
|
||||
|
||||
bool
|
||||
ConvertImage(size_t width, size_t height,
|
||||
const void* srcBegin, size_t srcStride, gl::OriginPos srcOrigin,
|
||||
WebGLTexelFormat srcFormat, bool srcPremultiplied,
|
||||
void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
|
||||
WebGLTexelFormat dstFormat, bool dstPremultiplied)
|
||||
WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride,
|
||||
const uint8_t* src, uint8_t* dst,
|
||||
WebGLTexelFormat srcFormat, bool srcPremultiplied,
|
||||
WebGLTexelFormat dstFormat, bool dstPremultiplied,
|
||||
size_t dstTexelSize)
|
||||
{
|
||||
if (width <= 0 || height <= 0)
|
||||
return true;
|
||||
|
||||
const bool FormatsRequireNoPremultiplicationOp =
|
||||
!HasAlpha(srcFormat) ||
|
||||
!HasColor(srcFormat) ||
|
||||
!HasColor(dstFormat);
|
||||
|
||||
if (srcFormat == dstFormat &&
|
||||
(FormatsRequireNoPremultiplicationOp || srcPremultiplied == dstPremultiplied))
|
||||
{
|
||||
// fast exit path: we just have to memcpy all the rows.
|
||||
//
|
||||
// The case where absolutely nothing needs to be done is supposed to have
|
||||
// been handled earlier (in TexImage2D_base, etc).
|
||||
//
|
||||
// So the case we're handling here is when even though no format conversion is needed,
|
||||
// we still might have to flip vertically and/or to adjust to a different stride.
|
||||
|
||||
MOZ_ASSERT(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
|
||||
|
||||
size_t row_size = width * dstTexelSize; // doesn't matter, src and dst formats agree
|
||||
const uint8_t* ptr = src;
|
||||
const uint8_t* src_end = src + height * srcStride;
|
||||
|
||||
uint8_t* dst_row = mPixelStoreFlipY
|
||||
? dst + (height-1) * dstStride
|
||||
: dst;
|
||||
ptrdiff_t dstStrideSigned(dstStride);
|
||||
ptrdiff_t dst_delta = mPixelStoreFlipY ? -dstStrideSigned : dstStrideSigned;
|
||||
|
||||
while(ptr != src_end) {
|
||||
memcpy(dst_row, ptr, row_size);
|
||||
ptr += srcStride;
|
||||
dst_row += dst_delta;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (srcFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion ||
|
||||
dstFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!width || !height)
|
||||
return true;
|
||||
|
||||
const bool shouldYFlip = (srcOrigin != dstOrigin);
|
||||
|
||||
const bool canSkipPremult = (!HasAlpha(srcFormat) ||
|
||||
!HasColor(srcFormat) ||
|
||||
!HasColor(dstFormat));
|
||||
|
||||
WebGLTexelPremultiplicationOp premultOp;
|
||||
if (canSkipPremult) {
|
||||
premultOp = WebGLTexelPremultiplicationOp::None;
|
||||
} else if (!srcPremultiplied && dstPremultiplied) {
|
||||
premultOp = WebGLTexelPremultiplicationOp::Premultiply;
|
||||
} else if (srcPremultiplied && !dstPremultiplied) {
|
||||
premultOp = WebGLTexelPremultiplicationOp::Unpremultiply;
|
||||
} else {
|
||||
premultOp = WebGLTexelPremultiplicationOp::None;
|
||||
uint8_t* dstStart = dst;
|
||||
ptrdiff_t signedDstStride = dstStride;
|
||||
if (mPixelStoreFlipY) {
|
||||
dstStart = dst + (height - 1) * dstStride;
|
||||
signedDstStride = -signedDstStride;
|
||||
}
|
||||
|
||||
const uint8_t* srcItr = (const uint8_t*)srcBegin;
|
||||
const uint8_t* const srcEnd = srcItr + srcStride * height;
|
||||
uint8_t* dstItr = (uint8_t*)dstBegin;
|
||||
ptrdiff_t dstItrStride = dstStride;
|
||||
if (shouldYFlip) {
|
||||
dstItr = dstItr + dstStride * (height - 1);
|
||||
dstItrStride = -dstItrStride;
|
||||
}
|
||||
WebGLImageConverter converter(width, height, src, dstStart, srcStride, signedDstStride);
|
||||
|
||||
if (srcFormat == dstFormat && premultOp == WebGLTexelPremultiplicationOp::None) {
|
||||
// Fast exit path: we just have to memcpy all the rows.
|
||||
//
|
||||
// The case where absolutely nothing needs to be done is supposed to have
|
||||
// been handled earlier (in TexImage2D_base, etc).
|
||||
//
|
||||
// So the case we're handling here is when even though no format conversion is
|
||||
// needed, we still might have to flip vertically and/or to adjust to a different
|
||||
// stride.
|
||||
const WebGLTexelPremultiplicationOp premultiplicationOp
|
||||
= FormatsRequireNoPremultiplicationOp ? WebGLTexelPremultiplicationOp::None
|
||||
: (!srcPremultiplied && dstPremultiplied) ? WebGLTexelPremultiplicationOp::Premultiply
|
||||
: (srcPremultiplied && !dstPremultiplied) ? WebGLTexelPremultiplicationOp::Unpremultiply
|
||||
: WebGLTexelPremultiplicationOp::None;
|
||||
|
||||
MOZ_ASSERT(shouldYFlip || srcStride != dstStride,
|
||||
"Performance trap -- should handle this case earlier to avoid memcpy");
|
||||
|
||||
const auto bytesPerPixel = TexelBytesForFormat(srcFormat);
|
||||
const size_t bytesPerRow = bytesPerPixel * width;
|
||||
|
||||
while (srcItr != srcEnd) {
|
||||
memcpy(dstItr, srcItr, bytesPerRow);
|
||||
srcItr += srcStride;
|
||||
dstItr += dstItrStride;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
WebGLImageConverter converter(width, height, srcItr, dstItr, srcStride, dstItrStride);
|
||||
converter.run(srcFormat, dstFormat, premultOp);
|
||||
converter.run(srcFormat, dstFormat, premultiplicationOp);
|
||||
|
||||
if (!converter.Success()) {
|
||||
// the dst image may be left uninitialized, so we better not try to
|
||||
|
@ -38,14 +38,6 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool ConvertImage(size_t width, size_t height,
|
||||
const void* srcBegin, size_t srcStride, gl::OriginPos srcOrigin,
|
||||
WebGLTexelFormat srcFormat, bool srcPremultiplied,
|
||||
void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
|
||||
WebGLTexelFormat dstFormat, bool dstPremultiplied);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// single precision float
|
||||
// seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,6 @@
|
||||
#define WEBGL_TEXTURE_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
@ -21,7 +20,6 @@
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
class WebGLContext;
|
||||
|
||||
namespace dom {
|
||||
class Element;
|
||||
@ -29,16 +27,18 @@ class ImageData;
|
||||
class ArrayBufferViewOrSharedArrayBufferView;
|
||||
} // namespace dom
|
||||
|
||||
namespace webgl {
|
||||
class TexUnpackBlob;
|
||||
} // namespace webgl
|
||||
|
||||
// Zero is not an integer power of two.
|
||||
inline bool
|
||||
IsPOTAssumingNonnegative(GLsizei x)
|
||||
{
|
||||
MOZ_ASSERT(x >= 0);
|
||||
return x && (x & (x-1)) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesTargetMatchDimensions(WebGLContext* webgl, TexImageTarget target, uint8_t dims,
|
||||
const char* funcName);
|
||||
|
||||
|
||||
// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
|
||||
// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
|
||||
class WebGLTexture final
|
||||
@ -46,145 +46,33 @@ class WebGLTexture final
|
||||
, public WebGLRefCountedObject<WebGLTexture>
|
||||
, public LinkedListElement<WebGLTexture>
|
||||
, public WebGLContextBoundObject
|
||||
, public WebGLFramebufferAttachable
|
||||
{
|
||||
// Friends
|
||||
friend class WebGLContext;
|
||||
friend class WebGLFramebuffer;
|
||||
|
||||
////////////////////////////////////
|
||||
// Members
|
||||
public:
|
||||
const GLuint mGLName;
|
||||
|
||||
protected:
|
||||
TexTarget mTarget;
|
||||
|
||||
static const uint8_t kMaxFaceCount = 6;
|
||||
uint8_t mFaceCount; // 6 for cube maps, 1 otherwise.
|
||||
|
||||
TexMinFilter mMinFilter;
|
||||
TexMagFilter mMagFilter;
|
||||
TexWrap mWrapS, mWrapT;
|
||||
|
||||
bool mImmutable; // Set by texStorage*
|
||||
uint8_t mImmutableLevelCount;
|
||||
|
||||
uint32_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
|
||||
uint32_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
|
||||
// You almost certainly don't want to query mMaxMipmapLevel.
|
||||
// You almost certainly want MaxEffectiveMipmapLevel().
|
||||
|
||||
GLenum mTexCompareMode;
|
||||
|
||||
// Resolvable optimizations:
|
||||
bool mIsResolved;
|
||||
FakeBlackType mResolved_FakeBlack;
|
||||
const GLint* mResolved_Swizzle; // nullptr means 'default swizzle'.
|
||||
|
||||
public:
|
||||
class ImageInfo;
|
||||
|
||||
// numLevels = log2(size) + 1
|
||||
// numLevels(16k) = log2(16k) + 1 = 14 + 1 = 15
|
||||
// numLevels(1M) = log2(1M) + 1 = 19.9 + 1 ~= 21
|
||||
// Or we can just max this out to 31, which is the number of unsigned bits in GLsizei.
|
||||
static const uint8_t kMaxLevelCount = 31;
|
||||
const GLuint mGLName;
|
||||
|
||||
// And in turn, it needs these forwards:
|
||||
protected:
|
||||
// We need to forward these.
|
||||
void SetImageInfo(ImageInfo* target, const ImageInfo& newInfo);
|
||||
void SetImageInfosAtLevel(uint32_t level, const ImageInfo& newInfo);
|
||||
GLenum mTarget;
|
||||
TexMinFilter mMinFilter;
|
||||
TexMagFilter mMagFilter;
|
||||
TexWrap mWrapS, mWrapT;
|
||||
|
||||
public:
|
||||
// We store information about the various images that are part of this
|
||||
// texture. (cubemap faces, mipmap levels)
|
||||
class ImageInfo
|
||||
{
|
||||
friend void WebGLTexture::SetImageInfo(ImageInfo* target,
|
||||
const ImageInfo& newInfo);
|
||||
friend void WebGLTexture::SetImageInfosAtLevel(uint32_t level,
|
||||
const ImageInfo& newInfo);
|
||||
size_t mFacesCount, mMaxLevelWithCustomImages;
|
||||
nsTArray<ImageInfo> mImageInfos;
|
||||
|
||||
public:
|
||||
static const ImageInfo kUndefined;
|
||||
bool mHaveGeneratedMipmap; // Set by generateMipmap
|
||||
bool mImmutable; // Set by texStorage*
|
||||
|
||||
// This is the "effective internal format" of the texture, an official
|
||||
// OpenGL spec concept, see OpenGL ES 3.0.3 spec, section 3.8.3, page
|
||||
// 126 and below.
|
||||
const webgl::FormatUsageInfo* const mFormat;
|
||||
size_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
|
||||
size_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
|
||||
|
||||
const uint32_t mWidth;
|
||||
const uint32_t mHeight;
|
||||
const uint32_t mDepth;
|
||||
WebGLTextureFakeBlackStatus mFakeBlackStatus;
|
||||
|
||||
protected:
|
||||
bool mIsDataInitialized;
|
||||
|
||||
std::set<WebGLFBAttachPoint*> mAttachPoints;
|
||||
|
||||
public:
|
||||
ImageInfo()
|
||||
: mFormat(LOCAL_GL_NONE)
|
||||
, mWidth(0)
|
||||
, mHeight(0)
|
||||
, mDepth(0)
|
||||
, mIsDataInitialized(false)
|
||||
{ }
|
||||
|
||||
ImageInfo(const webgl::FormatUsageInfo* format, uint32_t width, uint32_t height,
|
||||
uint32_t depth, bool isDataInitialized)
|
||||
: mFormat(format)
|
||||
, mWidth(width)
|
||||
, mHeight(height)
|
||||
, mDepth(depth)
|
||||
, mIsDataInitialized(isDataInitialized)
|
||||
{
|
||||
MOZ_ASSERT(mFormat);
|
||||
}
|
||||
|
||||
void Clear();
|
||||
|
||||
~ImageInfo() {
|
||||
if (!IsDefined())
|
||||
Clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
ImageInfo& operator =(const ImageInfo& a);
|
||||
|
||||
public:
|
||||
uint32_t MaxMipmapLevels() const {
|
||||
// GLES 3.0.4, 3.8 - Mipmapping: `floor(log2(largest_of_dims)) + 1`
|
||||
uint32_t largest = std::max(std::max(mWidth, mHeight), mDepth);
|
||||
return FloorLog2Size(largest) + 1;
|
||||
}
|
||||
|
||||
bool IsPowerOfTwo() const;
|
||||
|
||||
void AddAttachPoint(WebGLFBAttachPoint* attachPoint);
|
||||
void RemoveAttachPoint(WebGLFBAttachPoint* attachPoint);
|
||||
void OnRespecify() const;
|
||||
|
||||
size_t MemoryUsage() const;
|
||||
|
||||
bool IsDefined() const {
|
||||
if (mFormat == LOCAL_GL_NONE) {
|
||||
MOZ_ASSERT(!mWidth && !mHeight && !mDepth);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsDataInitialized() const { return mIsDataInitialized; }
|
||||
|
||||
void SetIsDataInitialized(bool isDataInitialized, WebGLTexture* tex);
|
||||
};
|
||||
|
||||
ImageInfo mImageInfoArr[kMaxLevelCount * kMaxFaceCount];
|
||||
|
||||
////////////////////////////////////
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
|
||||
@ -194,10 +82,10 @@ public:
|
||||
void Delete();
|
||||
|
||||
bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
|
||||
TexTarget Target() const { return mTarget; }
|
||||
GLenum Target() const { return mTarget; }
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
|
||||
@ -206,7 +94,6 @@ protected:
|
||||
~WebGLTexture() {
|
||||
DeleteOnce();
|
||||
}
|
||||
|
||||
public:
|
||||
////////////////////////////////////
|
||||
// GL calls
|
||||
@ -220,129 +107,290 @@ public:
|
||||
////////////////////////////////////
|
||||
// WebGLTextureUpload.cpp
|
||||
|
||||
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
|
||||
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView);
|
||||
void CompressedTexImage2D(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view);
|
||||
|
||||
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
|
||||
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::ImageData* imageData);
|
||||
void CompressedTexImage3D(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border, GLsizei imageSize,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
|
||||
|
||||
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
|
||||
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::Element* elem, ErrorResult* const out_error);
|
||||
|
||||
protected:
|
||||
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
|
||||
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType, webgl::TexUnpackBlob* blob);
|
||||
void CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLsizei width,
|
||||
GLsizei height, GLenum unpackFormat,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
|
||||
|
||||
bool ValidateTexImageSpecification(const char* funcName, TexImageTarget target,
|
||||
GLint level, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo);
|
||||
bool ValidateTexImageSelection(const char* funcName, TexImageTarget target,
|
||||
GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo);
|
||||
void CompressedTexSubImage3D(TexImageTarget texImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum unpackFormat, GLsizei imageSize,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
|
||||
|
||||
public:
|
||||
void TexStorage(const char* funcName, TexTarget target, GLsizei levels,
|
||||
GLenum sizedFormat, GLsizei width, GLsizei height, GLsizei depth);
|
||||
protected:
|
||||
void TexImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLenum internalFormat, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType, webgl::TexUnpackBlob* blob);
|
||||
void TexSubImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, webgl::TexUnpackBlob* blob);
|
||||
public:
|
||||
void CompressedTexImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
|
||||
void CompressedTexSubImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLenum sizedUnpackFormat,
|
||||
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
|
||||
void CopyTexImage2D(TexImageTarget target, GLint level, GLenum internalFormat,
|
||||
|
||||
void CopyTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
void CopyTexSubImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height);
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
void CopyTexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
void CopyTexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
|
||||
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult* const out_rv);
|
||||
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult* const out_rv);
|
||||
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
void TexImage3D(TexImageTarget target, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth, GLint border,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
|
||||
void TexStorage2D(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height);
|
||||
void TexStorage3D(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth);
|
||||
|
||||
|
||||
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult* const out_rv);
|
||||
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::ImageData* imageData, ErrorResult* const out_rv);
|
||||
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::Element* elem, ErrorResult* const out_rv);
|
||||
|
||||
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
|
||||
ErrorResult* const out_rv);
|
||||
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult* const out_rv);
|
||||
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::Element* elem, ErrorResult* const out_rv);
|
||||
|
||||
protected:
|
||||
void ClampLevelBaseAndMax();
|
||||
|
||||
void PopulateMipChain(uint32_t baseLevel, uint32_t maxLevel);
|
||||
/** Like glTexImage2D, but if the call may change the texture size, checks
|
||||
* any GL error generated by this glTexImage2D call and returns it.
|
||||
*/
|
||||
GLenum CheckedTexImage2D(TexImageTarget texImageTarget, GLint level,
|
||||
TexInternalFormat internalFormat, GLsizei width,
|
||||
GLsizei height, GLint border, TexFormat format,
|
||||
TexType type, const GLvoid* data);
|
||||
|
||||
uint32_t MaxEffectiveMipmapLevel() const;
|
||||
bool ValidateTexStorage(TexImageTarget texImageTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
const char* funcName);
|
||||
void SpecifyTexStorage(GLsizei levels, TexInternalFormat internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth);
|
||||
|
||||
static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
|
||||
GLenum rawTexImageTarget = texImageTarget.get();
|
||||
switch (rawTexImageTarget) {
|
||||
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 rawTexImageTarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
|
||||
GLint level, TexInternalFormat internalFormat,
|
||||
GLint xoffset, GLint yoffset, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height, bool isSub);
|
||||
|
||||
default:
|
||||
bool TexImageFromVideoElement(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::Element* elem);
|
||||
|
||||
// If jsArrayType is MaxTypedArrayViewType, it means no array.
|
||||
void TexImage2D_base(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLsizei srcStrideOrZero, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType, void* data, uint32_t byteLength,
|
||||
js::Scalar::Type jsArrayType, WebGLTexelFormat srcFormat,
|
||||
bool srcPremultiplied);
|
||||
void TexSubImage2D_base(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLsizei width, GLsizei height,
|
||||
GLsizei srcStrideOrZero, GLenum unpackFormat,
|
||||
GLenum unpackType, void* pixels, uint32_t byteLength,
|
||||
js::Scalar::Type jsArrayType, WebGLTexelFormat srcFormat,
|
||||
bool srcPremultiplied);
|
||||
|
||||
bool ValidateTexStorage(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
const char* info);
|
||||
bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info);
|
||||
|
||||
|
||||
public:
|
||||
// We store information about the various images that are part of this
|
||||
// texture. (cubemap faces, mipmap levels)
|
||||
class ImageInfo
|
||||
: public WebGLRectangleObject
|
||||
{
|
||||
public:
|
||||
ImageInfo()
|
||||
: mEffectiveInternalFormat(LOCAL_GL_NONE)
|
||||
, mDepth(0)
|
||||
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
|
||||
{}
|
||||
|
||||
ImageInfo(GLsizei width, GLsizei height, GLsizei depth,
|
||||
TexInternalFormat effectiveInternalFormat,
|
||||
WebGLImageDataStatus status)
|
||||
: WebGLRectangleObject(width, height)
|
||||
, mEffectiveInternalFormat(effectiveInternalFormat)
|
||||
, mDepth(depth)
|
||||
, mImageDataStatus(status)
|
||||
{
|
||||
// shouldn't use this constructor to construct a null ImageInfo
|
||||
MOZ_ASSERT(status != WebGLImageDataStatus::NoImageData);
|
||||
}
|
||||
|
||||
bool operator==(const ImageInfo& a) const {
|
||||
return mImageDataStatus == a.mImageDataStatus &&
|
||||
mWidth == a.mWidth &&
|
||||
mHeight == a.mHeight &&
|
||||
mDepth == a.mDepth &&
|
||||
mEffectiveInternalFormat == a.mEffectiveInternalFormat;
|
||||
}
|
||||
bool operator!=(const ImageInfo& a) const {
|
||||
return !(*this == a);
|
||||
}
|
||||
bool IsSquare() const {
|
||||
return mWidth == mHeight;
|
||||
}
|
||||
bool IsPositive() const {
|
||||
return mWidth > 0 && mHeight > 0 && mDepth > 0;
|
||||
}
|
||||
bool IsPowerOfTwo() const {
|
||||
MOZ_ASSERT(mWidth >= 0);
|
||||
MOZ_ASSERT(mHeight >= 0);
|
||||
return IsPOTAssumingNonnegative(mWidth) &&
|
||||
IsPOTAssumingNonnegative(mHeight);
|
||||
}
|
||||
bool HasUninitializedImageData() const {
|
||||
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
|
||||
}
|
||||
size_t MemoryUsage() const;
|
||||
|
||||
TexInternalFormat EffectiveInternalFormat() const {
|
||||
return mEffectiveInternalFormat;
|
||||
}
|
||||
GLsizei Depth() const { return mDepth; }
|
||||
|
||||
protected:
|
||||
// This is the "effective internal format" of the texture, an official
|
||||
// OpenGL spec concept, see OpenGL ES 3.0.3 spec, section 3.8.3, page
|
||||
// 126 and below.
|
||||
TexInternalFormat mEffectiveInternalFormat;
|
||||
|
||||
/* Used only for 3D textures.
|
||||
* Note that mWidth and mHeight are inherited from WebGLRectangleObject.
|
||||
* It's a pity to store a useless mDepth on non-3D texture images, but
|
||||
* the size of GLsizei is negligible compared to the typical size of a texture image.
|
||||
*/
|
||||
GLsizei mDepth;
|
||||
|
||||
WebGLImageDataStatus mImageDataStatus;
|
||||
|
||||
friend class WebGLTexture;
|
||||
};
|
||||
|
||||
private:
|
||||
static size_t FaceForTarget(TexImageTarget texImageTarget) {
|
||||
if (texImageTarget == LOCAL_GL_TEXTURE_2D ||
|
||||
texImageTarget == LOCAL_GL_TEXTURE_3D)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return texImageTarget.get() - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
}
|
||||
|
||||
ImageInfo& ImageInfoAtFace(uint8_t face, uint32_t level) {
|
||||
MOZ_ASSERT(face < mFaceCount);
|
||||
MOZ_ASSERT(level < kMaxLevelCount);
|
||||
size_t pos = (level * mFaceCount) + face;
|
||||
return mImageInfoArr[pos];
|
||||
ImageInfo& ImageInfoAtFace(size_t face, GLint level) {
|
||||
MOZ_ASSERT(face < mFacesCount,
|
||||
"Wrong face index, must be 0 for TEXTURE_2D or TEXTURE_3D,"
|
||||
" and at most 5 for cube maps.");
|
||||
|
||||
// No need to check level as a wrong value would be caught by
|
||||
// ElementAt().
|
||||
return mImageInfos.ElementAt(level * mFacesCount + face);
|
||||
}
|
||||
|
||||
const ImageInfo& ImageInfoAtFace(uint8_t face, uint32_t level) const {
|
||||
return const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level);
|
||||
const ImageInfo& ImageInfoAtFace(size_t face, GLint level) const {
|
||||
return const_cast<const ImageInfo&>(
|
||||
const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level)
|
||||
);
|
||||
}
|
||||
|
||||
public:
|
||||
ImageInfo& ImageInfoAt(TexImageTarget texImageTarget, GLint level) {
|
||||
auto face = FaceForTarget(texImageTarget);
|
||||
ImageInfo& ImageInfoAt(TexImageTarget imageTarget, GLint level) {
|
||||
size_t face = FaceForTarget(imageTarget);
|
||||
return ImageInfoAtFace(face, level);
|
||||
}
|
||||
|
||||
const ImageInfo& ImageInfoAt(TexImageTarget texImageTarget, GLint level) const {
|
||||
return const_cast<WebGLTexture*>(this)->ImageInfoAt(texImageTarget, level);
|
||||
}
|
||||
|
||||
void SetImageInfoAt(TexImageTarget texImageTarget, GLint level,
|
||||
const ImageInfo& val)
|
||||
const ImageInfo& ImageInfoAt(TexImageTarget imageTarget, GLint level) const
|
||||
{
|
||||
ImageInfo* target = &ImageInfoAt(texImageTarget, level);
|
||||
SetImageInfo(target, val);
|
||||
return const_cast<WebGLTexture*>(this)->ImageInfoAt(imageTarget, level);
|
||||
}
|
||||
|
||||
const ImageInfo& BaseImageInfo() const {
|
||||
if (mBaseMipmapLevel >= kMaxLevelCount)
|
||||
return ImageInfo::kUndefined;
|
||||
bool HasImageInfoAt(TexImageTarget imageTarget, GLint level) const {
|
||||
size_t face = FaceForTarget(imageTarget);
|
||||
CheckedUint32 checked_index = CheckedUint32(level) * mFacesCount + face;
|
||||
return checked_index.isValid() &&
|
||||
checked_index.value() < mImageInfos.Length() &&
|
||||
ImageInfoAt(imageTarget, level).mImageDataStatus != WebGLImageDataStatus::NoImageData;
|
||||
}
|
||||
|
||||
return ImageInfoAtFace(0, mBaseMipmapLevel);
|
||||
ImageInfo& ImageInfoBase() {
|
||||
return ImageInfoAtFace(0, 0);
|
||||
}
|
||||
|
||||
const ImageInfo& ImageInfoBase() const {
|
||||
return ImageInfoAtFace(0, 0);
|
||||
}
|
||||
|
||||
size_t MemoryUsage() const;
|
||||
|
||||
bool InitializeImageData(const char* funcName, TexImageTarget target, uint32_t level);
|
||||
void SetImageDataStatus(TexImageTarget imageTarget, GLint level,
|
||||
WebGLImageDataStatus newStatus)
|
||||
{
|
||||
MOZ_ASSERT(HasImageInfoAt(imageTarget, level));
|
||||
ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
|
||||
// There is no way to go from having image data to not having any.
|
||||
MOZ_ASSERT(newStatus != WebGLImageDataStatus::NoImageData ||
|
||||
imageInfo.mImageDataStatus == WebGLImageDataStatus::NoImageData);
|
||||
|
||||
if (imageInfo.mImageDataStatus != newStatus)
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
|
||||
imageInfo.mImageDataStatus = newStatus;
|
||||
}
|
||||
|
||||
bool EnsureInitializedImageData(TexImageTarget imageTarget, GLint level);
|
||||
|
||||
protected:
|
||||
bool EnsureImageDataInitialized(const char* funcName, TexImageTarget target,
|
||||
uint32_t level);
|
||||
|
||||
void EnsureMaxLevelWithCustomImagesAtLeast(size_t maxLevelWithCustomImages) {
|
||||
mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages,
|
||||
maxLevelWithCustomImages);
|
||||
mImageInfos.EnsureLengthAtLeast((mMaxLevelWithCustomImages + 1) * mFacesCount);
|
||||
}
|
||||
|
||||
bool CheckFloatTextureFilterParams() const {
|
||||
// Without OES_texture_float_linear, only NEAREST and
|
||||
@ -357,7 +405,33 @@ protected:
|
||||
mWrapT == LOCAL_GL_CLAMP_TO_EDGE;
|
||||
}
|
||||
|
||||
bool DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const;
|
||||
|
||||
public:
|
||||
void Bind(TexTarget texTarget);
|
||||
|
||||
void SetImageInfo(TexImageTarget target, GLint level, GLsizei width,
|
||||
GLsizei height, GLsizei depth, TexInternalFormat format,
|
||||
WebGLImageDataStatus status);
|
||||
|
||||
void SetMinFilter(TexMinFilter minFilter) {
|
||||
mMinFilter = minFilter;
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetMagFilter(TexMagFilter magFilter) {
|
||||
mMagFilter = magFilter;
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetWrapS(TexWrap wrapS) {
|
||||
mWrapS = wrapS;
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetWrapT(TexWrap wrapT) {
|
||||
mWrapT = wrapT;
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
TexMinFilter MinFilter() const { return mMinFilter; }
|
||||
|
||||
bool DoesMinFilterRequireMipmap() const {
|
||||
return !(mMinFilter == LOCAL_GL_NEAREST ||
|
||||
mMinFilter == LOCAL_GL_LINEAR);
|
||||
@ -367,31 +441,51 @@ public:
|
||||
|
||||
void SetCustomMipmap();
|
||||
|
||||
bool IsFirstImagePowerOfTwo() const {
|
||||
return ImageInfoBase().IsPowerOfTwo();
|
||||
}
|
||||
|
||||
bool AreAllLevel0ImageInfosEqual() const;
|
||||
|
||||
bool IsMipmapComplete() const;
|
||||
|
||||
bool IsCubeComplete() const;
|
||||
|
||||
bool IsComplete(const char** const out_reason) const;
|
||||
|
||||
bool IsMipmapCubeComplete() const;
|
||||
|
||||
bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); }
|
||||
void SetFakeBlackStatus(WebGLTextureFakeBlackStatus x);
|
||||
|
||||
// Resolve cache optimizations
|
||||
protected:
|
||||
bool GetFakeBlackType(const char* funcName, uint32_t texUnit,
|
||||
FakeBlackType* const out_fakeBlack);
|
||||
public:
|
||||
bool ResolveForDraw(const char* funcName, uint32_t texUnit,
|
||||
FakeBlackType* const out_fakeBlack);
|
||||
bool IsImmutable() const { return mImmutable; }
|
||||
void SetImmutable() { mImmutable = true; }
|
||||
|
||||
void InvalidateResolveCache() { mIsResolved = false; }
|
||||
void SetBaseMipmapLevel(size_t level) { mBaseMipmapLevel = level; }
|
||||
void SetMaxMipmapLevel(size_t level) { mMaxMipmapLevel = level; }
|
||||
|
||||
// Clamping (from ES 3.0.4, section 3.8 - Texturing). When not immutable,
|
||||
// the ranges must be guarded.
|
||||
size_t EffectiveBaseMipmapLevel() const {
|
||||
if (IsImmutable())
|
||||
return std::min(mBaseMipmapLevel, mMaxLevelWithCustomImages);
|
||||
return mBaseMipmapLevel;
|
||||
}
|
||||
size_t EffectiveMaxMipmapLevel() const {
|
||||
if (IsImmutable()) {
|
||||
return mozilla::clamped(mMaxMipmapLevel, EffectiveBaseMipmapLevel(),
|
||||
mMaxLevelWithCustomImages);
|
||||
}
|
||||
return std::min(mMaxMipmapLevel, mMaxLevelWithCustomImages);
|
||||
}
|
||||
bool IsMipmapRangeValid() const;
|
||||
|
||||
size_t MaxLevelWithCustomImages() const { return mMaxLevelWithCustomImages; }
|
||||
|
||||
// Returns the current fake-black-status, except if it was Unknown,
|
||||
// in which case this function resolves it first, so it never returns Unknown.
|
||||
WebGLTextureFakeBlackStatus ResolvedFakeBlackStatus();
|
||||
};
|
||||
|
||||
inline TexImageTarget
|
||||
TexImageTargetForTargetAndFace(TexTarget target, uint8_t face)
|
||||
TexImageTargetForTargetAndFace(TexTarget target, size_t face)
|
||||
{
|
||||
switch (target.get()) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
@ -406,23 +500,6 @@ TexImageTargetForTargetAndFace(TexTarget target, uint8_t face)
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::layers::Image>
|
||||
ImageFromVideo(dom::HTMLVideoElement* elem);
|
||||
|
||||
GLenum
|
||||
DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLsizei width, GLsizei height,
|
||||
GLsizei depth, const void* data);
|
||||
GLenum
|
||||
DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, const webgl::PackingInfo& pi, const void* data);
|
||||
GLenum
|
||||
DoCompressedTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLenum sizedUnpackFormat,
|
||||
GLsizei dataSize, const void* data);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // WEBGL_TEXTURE_H_
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,7 @@ WebGLTimerQuery::Delete()
|
||||
WebGLContext*
|
||||
WebGLTimerQuery::GetParentObject() const
|
||||
{
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,7 +41,7 @@ WebGLTransformFeedback::Delete()
|
||||
WebGLContext*
|
||||
WebGLTransformFeedback::GetParentObject() const
|
||||
{
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -18,10 +18,12 @@ typedef bool WebGLboolean;
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* WebGLTextureFakeBlackStatus is an enum to track what needs to use a dummy 1x1 black
|
||||
* texture, which we refer to as a 'fake black' texture.
|
||||
* WebGLContextFakeBlackStatus and WebGLTextureFakeBlackStatus are enums to
|
||||
* track what needs to use a dummy 1x1 black texture, which we refer to as a
|
||||
* 'fake black' texture.
|
||||
*
|
||||
* There are two things that can cause us to use such 'fake black' textures:
|
||||
* There are generally two things that can cause us to use such 'fake black'
|
||||
* textures:
|
||||
*
|
||||
* (1) OpenGL ES rules on sampling incomplete textures specify that they
|
||||
* must be sampled as RGBA(0, 0, 0, 1) (opaque black). We have to implement these rules
|
||||
@ -36,12 +38,23 @@ namespace mozilla {
|
||||
* uninitialized image data must be exposed to WebGL as if it were filled
|
||||
* with zero bytes, which means it's either opaque or transparent black
|
||||
* depending on whether the image format has alpha.
|
||||
*
|
||||
* Why are there _two_ separate enums there, WebGLContextFakeBlackStatus
|
||||
* and WebGLTextureFakeBlackStatus? That's because each texture must know the precise
|
||||
* reason why it needs to be faked (incomplete texture vs. uninitialized image data),
|
||||
* whereas the WebGL context can only know whether _any_ faking is currently needed at all.
|
||||
*/
|
||||
enum class WebGLContextFakeBlackStatus : uint8_t {
|
||||
Unknown,
|
||||
NotNeeded,
|
||||
Needed
|
||||
};
|
||||
|
||||
enum class FakeBlackType : uint8_t {
|
||||
None,
|
||||
RGBA0001, // Incomplete textures and uninitialized no-alpha color textures.
|
||||
RGBA0000, // Uninitialized with-alpha color textures.
|
||||
enum class WebGLTextureFakeBlackStatus : uint8_t {
|
||||
Unknown,
|
||||
NotNeeded,
|
||||
IncompleteTexture,
|
||||
UninitializedImageData
|
||||
};
|
||||
|
||||
/*
|
||||
@ -102,7 +115,6 @@ enum class WebGLTexelFormat : uint8_t {
|
||||
RA32F, // OES_texture_float
|
||||
// 3-channel formats
|
||||
RGB8,
|
||||
RGBX8, // used for DOM elements. Source format only.
|
||||
BGRX8, // used for DOM elements. Source format only.
|
||||
RGB565,
|
||||
RGB16F, // OES_texture_half_float
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
bool IsVertexArray();
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
return Context();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
|
||||
|
@ -54,7 +54,6 @@ UNIFIED_SOURCES += [
|
||||
# WebGL Sources
|
||||
UNIFIED_SOURCES += [
|
||||
'MurmurHash3.cpp',
|
||||
'TexUnpackBlob.cpp',
|
||||
'WebGL1Context.cpp',
|
||||
'WebGL1ContextBuffers.cpp',
|
||||
'WebGL1ContextUniforms.cpp',
|
||||
|
@ -78,27 +78,26 @@ function expectResult(target, successMessage, failureMessage) {
|
||||
}
|
||||
}
|
||||
|
||||
function createGreySRGBATexture(gl, color) {
|
||||
function createGreysRGBTexture(gl, color) {
|
||||
var numPixels = gl.drawingBufferWidth * gl.drawingBufferHeight;
|
||||
var size = numPixels * 4;
|
||||
var size = numPixels * 3;
|
||||
var buf = new Uint8Array(size);
|
||||
for (var ii = 0; ii < numPixels; ++ii) {
|
||||
var off = ii * 3;
|
||||
buf[off + 0] = color;
|
||||
buf[off + 1] = color;
|
||||
buf[off + 2] = color;
|
||||
buf[off + 3] = 0xff;
|
||||
}
|
||||
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D,
|
||||
0,
|
||||
ext.SRGB_ALPHA_EXT,
|
||||
ext.SRGB_EXT,
|
||||
gl.drawingBufferWidth,
|
||||
gl.drawingBufferHeight,
|
||||
0,
|
||||
ext.SRGB_ALPHA_EXT,
|
||||
ext.SRGB_EXT,
|
||||
gl.UNSIGNED_BYTE,
|
||||
buf);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
@ -267,11 +266,11 @@ function runTextureReadConversionTest() {
|
||||
gl.uniform1i(gl.getUniformLocation(program, "tex2d"), 0);
|
||||
|
||||
for (var ii = 0; ii < conversions.length; ii++) {
|
||||
var tex = createGreySRGBATexture(gl, conversions[ii][0]);
|
||||
var tex = createGreysRGBTexture(gl, conversions[ii][0]);
|
||||
wtu.drawQuad(gl);
|
||||
expectResult(conversions[ii][1],
|
||||
"sRGBA texture read returned correct data",
|
||||
"sRGBA texture read returned incorrect data");
|
||||
"sRGB texture read returned correct data",
|
||||
"sRGB texture read returned incorrect data");
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,14 +279,13 @@ function runFramebufferTextureConversionTest() {
|
||||
debug("Test the conversion of colors from linear to sRGB on framebuffer (texture) write");
|
||||
|
||||
var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]);
|
||||
var tex = createGreySRGBATexture(gl, 0);
|
||||
var tex = createGreysRGBTexture(gl, 0);
|
||||
var fbo = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT');
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
|
||||
|
||||
// Draw
|
||||
@ -309,7 +307,6 @@ function runFramebufferTextureConversionTest() {
|
||||
"framebuffer (texture) read returned incorrect data");
|
||||
}
|
||||
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
}
|
||||
|
||||
@ -330,7 +327,6 @@ function runFramebufferRenderbufferConversionTest() {
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT');
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
|
||||
|
||||
return fbo;
|
||||
@ -356,8 +352,6 @@ function runFramebufferRenderbufferConversionTest() {
|
||||
"framebuffer (renderbuffer) read returned the correct data",
|
||||
"framebuffer (renderbuffer) read returned incorrect data");
|
||||
}
|
||||
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
}
|
||||
|
||||
debug("");
|
||||
|
@ -131,8 +131,7 @@ function runTextureCreationTest(testProgram, extensionEnabled)
|
||||
}
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, data);
|
||||
if (expectFailure) {
|
||||
wtu.glErrorShouldBeIn(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION],
|
||||
"floating-point texture allocation must be disallowed if OES_texture_float isn't enabled");
|
||||
glErrorShouldBe(gl, gl.INVALID_ENUM, "floating-point texture allocation must be disallowed if OES_texture_float isn't enabled");
|
||||
return;
|
||||
} else {
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed if OES_texture_float is enabled");
|
||||
|
@ -76,7 +76,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
|
||||
// Deleting a texture bound to the currently-bound fbo is the same as
|
||||
// detaching the textue from fbo first, then delete the texture.
|
||||
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
|
||||
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "null");
|
||||
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
|
||||
shouldBeFalse("gl.isTexture(tex)");
|
||||
shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
|
||||
@ -128,7 +128,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
|
||||
// Deleting a renderbuffer bound to the currently-bound fbo is the same as
|
||||
// detaching the renderbuffer from fbo first, then delete the renderbuffer.
|
||||
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
|
||||
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "null");
|
||||
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
|
||||
shouldBeFalse("gl.isRenderbuffer(rbo)");
|
||||
shouldBeNull("gl.getParameter(gl.RENDERBUFFER_BINDING)");
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
|
||||
@ -263,7 +263,7 @@ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
|
||||
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
|
||||
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)");
|
||||
shouldGenerateGLError(gl, gl.NONE, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)");
|
||||
shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
|
||||
// Bind backbuffer.
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
|
||||
|
@ -58,53 +58,53 @@ function teardown(gl, tex) {
|
||||
gl.deleteTexture(tex);
|
||||
}
|
||||
|
||||
function testrunner(gl, expectedList, desc, fn) {
|
||||
function testrunner(gl, expected, desc, fn) {
|
||||
var tex = setup(gl);
|
||||
fn();
|
||||
wtu.glErrorShouldBeIn(gl, expectedList, desc);
|
||||
glErrorShouldBe(gl, expected, desc);
|
||||
teardown(gl, tex);
|
||||
}
|
||||
|
||||
var data = new Uint8Array(4);
|
||||
testrunner(gl, [gl.INVALID_OPERATION], "not enough data", function(){
|
||||
testrunner(gl, gl.INVALID_OPERATION, "not enough data", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,1,0,gl.RGBA,gl.UNSIGNED_BYTE, data);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_OPERATION], "not enough data", function(){
|
||||
testrunner(gl, gl.INVALID_OPERATION, "not enough data", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,2,0,gl.RGBA,gl.UNSIGNED_BYTE, data);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_ENUM], "bad target", function(){
|
||||
testrunner(gl, gl.INVALID_ENUM, "bad target", function(){
|
||||
gl.texImage2D(gl.FLOAT, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE], "bad internal format/format", function(){
|
||||
testrunner(gl, gl.INVALID_ENUM, "bad internal format/format", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.FLOAT, 1,1,0,gl.FLOAT,gl.UNSIGNED_BYTE, null);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_VALUE], "border > 0", function(){
|
||||
testrunner(gl, gl.INVALID_VALUE, "border > 0", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,48,gl.RGBA,gl.UNSIGNED_BYTE, null);
|
||||
});
|
||||
// The spec says zero size is OK. If you disagree please list the section
|
||||
// in the spec that details this issue.
|
||||
testrunner(gl, [gl.NO_ERROR], "zero size", function(){
|
||||
testrunner(gl, gl.NO_ERROR, "zero size", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_VALUE], "negative width", function(){
|
||||
testrunner(gl, gl.INVALID_VALUE, "negative width", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, -1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_VALUE], "negative height", function(){
|
||||
testrunner(gl, gl.INVALID_VALUE, "negative height", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,-1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "bad format", function(){
|
||||
testrunner(gl, gl.INVALID_ENUM, "bad format", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.FLOAT,gl.UNSIGNED_BYTE, null);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_ENUM], "bad type", function(){
|
||||
testrunner(gl, gl.INVALID_ENUM, "bad type", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.TEXTURE_2D, null);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_OPERATION], "not enough data", function(){
|
||||
testrunner(gl, gl.INVALID_OPERATION, "not enough data", function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array(3));
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_OPERATION], "format and type incompatible",function(){
|
||||
testrunner(gl, gl.INVALID_OPERATION, "format and type incompatible",function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_SHORT_5_6_5, null);
|
||||
});
|
||||
testrunner(gl, [gl.INVALID_OPERATION], "format and type incompatible",function(){
|
||||
testrunner(gl, gl.INVALID_OPERATION, "format and type incompatible",function(){
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1,1,0,gl.RGB,gl.UNSIGNED_SHORT_4_4_4_4, null);
|
||||
});
|
||||
|
||||
|
@ -31,7 +31,6 @@ OTHER DEALINGS IN THE SOFTWARE.
|
||||
<link rel="stylesheet" type="text/css" href="../unit.css" />
|
||||
<script type="application/x-javascript" src="../unit.js"></script>
|
||||
<script type="application/x-javascript" src="../util.js"></script>
|
||||
<script src="../../resources/webgl-test-utils.js"></script>
|
||||
<script type="application/x-javascript">
|
||||
|
||||
Tests.startUnit = function () {
|
||||
@ -52,7 +51,7 @@ Tests.teardown = function(gl,tex) {
|
||||
}
|
||||
|
||||
Tests.testTexImage2D = function(gl) {
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,2,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]));
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,2,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]));
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "not enough data", function(){
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 2,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
|
||||
});
|
||||
@ -71,10 +70,10 @@ Tests.testTexImage2D = function(gl) {
|
||||
assertOk("zero size", function(){
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 0,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
|
||||
});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative width", function(){
|
||||
assertSomeGLError(gl, "negative width", function(){
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, -1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
|
||||
});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative height", function(){
|
||||
assertSomeGLError(gl, "negative height", function(){
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 1,-1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
|
||||
});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative x", function(){
|
||||
|
@ -1001,11 +1001,12 @@ function wrapGLContext(gl) {
|
||||
// Assert that f generates a specific GL error.
|
||||
function assertGLError(gl, err, name, f) {
|
||||
if (f == null) { f = name; name = null; }
|
||||
var r = false;
|
||||
var glErr = 0;
|
||||
try { f(); } catch(e) { glErr = e.glError; }
|
||||
try { f(); } catch(e) { r=true; glErr = e.glError; }
|
||||
if (glErr !== err) {
|
||||
if (glErr === undefined) {
|
||||
testFailed("assertGLError: UNEXPECTED EXCEPTION", name, f);
|
||||
testFailed("assertGLError: UNEXPCETED EXCEPTION", name, f);
|
||||
} else {
|
||||
testFailed("assertGLError: expected: " + getGLErrorAsString(gl, err) +
|
||||
" actual: " + getGLErrorAsString(gl, glErr), name, f);
|
||||
@ -1015,40 +1016,6 @@ function assertGLError(gl, err, name, f) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Assert that f generates a specific GL error.
|
||||
function assertGLErrorIn(gl, expectedErrorList, name, f) {
|
||||
if (f == null) { f = name; name = null; }
|
||||
|
||||
var actualError = 0;
|
||||
try {
|
||||
f();
|
||||
} catch(e) {
|
||||
if ('glError' in e) {
|
||||
actualError = e.glError;
|
||||
} else {
|
||||
testFailed("assertGLErrorIn: UNEXPECTED EXCEPTION", name, f);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var expectedErrorStrList = [];
|
||||
var expectedErrorSet = {};
|
||||
for (var i in expectedErrorList) {
|
||||
var cur = expectedErrorList[i];
|
||||
expectedErrorSet[cur] = true;
|
||||
expectedErrorStrList.push(getGLErrorAsString(gl, cur));
|
||||
}
|
||||
var expectedErrorListStr = "[" + expectedErrorStrList.join(", ") + "]";
|
||||
|
||||
if (actualError in expectedErrorSet) {
|
||||
return true;
|
||||
}
|
||||
|
||||
testFailed("assertGLErrorIn: expected: " + expectedErrorListStr +
|
||||
" actual: " + getGLErrorAsString(gl, actualError), name, f);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assert that f generates some GL error. Used in situations where it's
|
||||
// ambigious which of multiple possible errors will be generated.
|
||||
function assertSomeGLError(gl, name, f) {
|
||||
|
@ -132,17 +132,16 @@ if (!gl) {
|
||||
glErrorShouldBe(gl, gl.INVALID_ENUM,
|
||||
"calling framebufferRenderbuffer with attachment = COLOR_ATTACHMENT1 should generate INVALID_ENUM.");
|
||||
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
"attaching a texture to a framebuffer should succeed.");
|
||||
|
||||
// Must have a valid attachment, otherwise may also generate INVALID_OPERATION.
|
||||
gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER,
|
||||
gl.COLOR_ATTACHMENT0,
|
||||
desktopGL.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
|
||||
glErrorShouldBe(gl, gl.INVALID_ENUM,
|
||||
"calling getFramebufferAttachmentParameter with pname = GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING should generate INVALID_ENUM.");
|
||||
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
"attaching a texture to a framebuffer should succeed.");
|
||||
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
|
||||
glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
"detaching a texture from a framebuffer should succeed.");
|
||||
|
@ -634,6 +634,31 @@ function create3DContextWithWrapperThatThrowsOnGLError(canvas) {
|
||||
return wrap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests that an evaluated expression generates a specific GL error.
|
||||
* @param {!WebGLContext} gl The WebGLContext to use.
|
||||
* @param {number} glError The expected gl error.
|
||||
* @param {string} evalSTr The string to evaluate.
|
||||
*/
|
||||
var shouldGenerateGLError = function(gl, glError, evalStr) {
|
||||
var exception;
|
||||
try {
|
||||
eval(evalStr);
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
if (exception) {
|
||||
testFailed(evalStr + " threw exception " + exception);
|
||||
} else {
|
||||
var err = gl.getError();
|
||||
if (err != glError) {
|
||||
testFailed(evalStr + " expected: " + getGLErrorAsString(gl, glError) + ". Was " + getGLErrorAsString(gl, err) + ".");
|
||||
} else {
|
||||
testPassed(evalStr + " was expected value: " + getGLErrorAsString(gl, glError) + ".");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests that the first error GL returns is the specified error.
|
||||
* @param {!WebGLContext} gl The WebGLContext to use.
|
||||
@ -652,84 +677,6 @@ var glErrorShouldBe = function(gl, glError, opt_msg) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests that the first error GL returns is in the specified error list.
|
||||
* @param {!WebGLContext} gl The WebGLContext to use.
|
||||
* @param {!Array.<number>} expectedErrorList The list of expected gl errors.
|
||||
* @param {string} opt_msg
|
||||
*/
|
||||
var glErrorShouldBeIn = function(gl, expectedErrorList, opt_msg) {
|
||||
opt_msg = opt_msg || "";
|
||||
|
||||
var expectedErrorStrList = [];
|
||||
var expectedErrorSet = {};
|
||||
|
||||
for (var i in expectedErrorList) {
|
||||
var cur = expectedErrorList[i];
|
||||
|
||||
expectedErrorStrList.push(getGLErrorAsString(gl, cur));
|
||||
expectedErrorSet[cur] = true;
|
||||
}
|
||||
|
||||
var expectedErrorStr = "[" + expectedErrorStrList.join(", ") + "]";
|
||||
|
||||
var actualError = gl.getError();
|
||||
if (actualError in expectedErrorSet) {
|
||||
testPassed("getError was in expected values: " + expectedErrorStr + " : " + opt_msg);
|
||||
} else {
|
||||
testFailed("getError expected: " + expectedErrorStr +
|
||||
". Was " + getGLErrorAsString(gl, actualError) + " : " + opt_msg);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests that an evaluated expression generates a specific GL error.
|
||||
* @param {!WebGLContext} gl The WebGLContext to use.
|
||||
* @param {number} glError The expected gl error.
|
||||
* @param {string} evalSTr The string to evaluate.
|
||||
*/
|
||||
var shouldGenerateGLError = function(gl, glError, evalStr) {
|
||||
glErrorShouldBe(gl, 0,
|
||||
"Should not be pre-existing errors during call to"
|
||||
+ " shouldGenerateGLError().");
|
||||
|
||||
var exception;
|
||||
try {
|
||||
eval(evalStr);
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
if (exception) {
|
||||
testFailed(evalStr + " threw exception " + exception);
|
||||
} else {
|
||||
glErrorShouldBe(gl, glError, evalStr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests that an evaluated expression generates a GL error from a list.
|
||||
* @param {!WebGLContext} gl The WebGLContext to use.
|
||||
* @param {!Array.<number>} expectedErrorList The list of expected gl errors.
|
||||
* @param {string} evalSTr The string to evaluate.
|
||||
*/
|
||||
var shouldGenerateGLErrorIn = function(gl, expectedErrorList, evalStr) {
|
||||
glErrorShouldBe(gl, 0,
|
||||
"Should not be pre-existing errors during call to"
|
||||
+ " shouldGenerateGLErrorIn().");
|
||||
|
||||
var exception;
|
||||
try {
|
||||
eval(evalStr);
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
if (exception) {
|
||||
testFailed(evalStr + " threw exception " + exception);
|
||||
} else {
|
||||
glErrorShouldBeIn(gl, expectedErrorList, evalStr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Links a WebGL program, throws if there are errors.
|
||||
* @param {!WebGLContext} gl The WebGLContext to use.
|
||||
@ -1418,7 +1365,6 @@ return {
|
||||
getUrlArguments: getUrlArguments,
|
||||
glEnumToString: glEnumToString,
|
||||
glErrorShouldBe: glErrorShouldBe,
|
||||
glErrorShouldBeIn: glErrorShouldBeIn,
|
||||
fillTexture: fillTexture,
|
||||
insertImage: insertImage,
|
||||
loadImageAsync: loadImageAsync,
|
||||
|
@ -39,8 +39,8 @@ function testTexImage2D(testCase)
|
||||
" border: " + testCase.border;
|
||||
|
||||
gl.texImage2D(testCase.target, level, testCase.internalFormat, width, height, testCase.border, testCase.format, testCase.type, null);
|
||||
errors = testCase.expectedErrors;
|
||||
wtu.glErrorShouldBeIn(gl, errors, msg);
|
||||
error = testCase.expectedError;
|
||||
glErrorShouldBe(gl, error, msg);
|
||||
}
|
||||
|
||||
function testTexSubImage2D(testCase)
|
||||
@ -55,26 +55,26 @@ function testTexSubImage2D(testCase)
|
||||
" type: " + enumToString(testCase.type);
|
||||
var array = new Uint8Array(width * height * 4);
|
||||
gl.texSubImage2D(testCase.target, level, xoffset, yoffset, width, height, testCase.format, testCase.type, array);
|
||||
errors = testCase.expectedErrors;
|
||||
wtu.glErrorShouldBeIn(gl, errors, msg);
|
||||
error = testCase.expectedError;
|
||||
glErrorShouldBe(gl, error, msg);
|
||||
}
|
||||
|
||||
function testTexParameter(testCase)
|
||||
{
|
||||
var msg = "paramName: " + enumToString(testCase.pname);
|
||||
errors = testCase.expectedErrors;
|
||||
error = testCase.expectedError;
|
||||
gl.texParameteri(testCase.target, testCase.pname, testCase.param);
|
||||
wtu.glErrorShouldBeIn(gl, errors, msg);
|
||||
glErrorShouldBe(gl, error, msg);
|
||||
gl.texParameterf(testCase.target, testCase.pname, testCase.param);
|
||||
wtu.glErrorShouldBeIn(gl, errors, msg);
|
||||
glErrorShouldBe(gl, error, msg);
|
||||
}
|
||||
|
||||
function testGetTexParameter(testCase)
|
||||
{
|
||||
var msg = "paramName: " + enumToString(testCase.pname);
|
||||
errors = testCase.expectedErrors;
|
||||
error = testCase.expectedError;
|
||||
gl.getTexParameter(testCase.target, testCase.pname);
|
||||
wtu.glErrorShouldBeIn(gl, errors, msg);
|
||||
glErrorShouldBe(gl, error, msg);
|
||||
}
|
||||
|
||||
function testCopyTexImage2D(testCase)
|
||||
@ -96,8 +96,8 @@ function testCopyTexImage2D(testCase)
|
||||
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
|
||||
|
||||
gl.copyTexImage2D(testCase.target, level, testCase.internalFormat, x, y, width, height, testCase.border);
|
||||
errors = testCase.expectedErrors;
|
||||
wtu.glErrorShouldBeIn(gl, errors, msg);
|
||||
error = testCase.expectedError;
|
||||
glErrorShouldBe(gl, error, msg);
|
||||
}
|
||||
|
||||
function testCopyTexSubImage2D(testCase)
|
||||
@ -124,8 +124,8 @@ function testCopyTexSubImage2D(testCase)
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
gl.copyTexSubImage2D(testCase.target, level, xoffset, yoffset, x, y, width, height);
|
||||
errors = testCase.expectedErrors;
|
||||
wtu.glErrorShouldBeIn(gl, errors, msg);
|
||||
error = testCase.expectedError;
|
||||
glErrorShouldBe(gl, error, msg);
|
||||
}
|
||||
|
||||
function testCopyFromInternalFBO(testCase)
|
||||
@ -159,8 +159,8 @@ function testCopyFromInternalFBO(testCase)
|
||||
glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
gl.copyTexImage2D(target, level, testCase.internalFormat, x, y, width, height, border);
|
||||
}
|
||||
errors = testCase.expectedErrors;
|
||||
wtu.glErrorShouldBeIn(gl, errors, msg);
|
||||
error = testCase.expectedError;
|
||||
glErrorShouldBe(gl, error, msg);
|
||||
}
|
||||
|
||||
description("Validate tex functions input parameters");
|
||||
@ -179,37 +179,37 @@ var testCases =
|
||||
border: 0,
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
expectedErrors: [gl.INVALID_ENUM]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
internalFormat: 0x1903, // GL_RED
|
||||
border: 0,
|
||||
format: 0x1903, // GL_RED
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
expectedErrors: [gl.INVALID_ENUM, gl.INVALID_VALUE]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
internalFormat: gl.RGBA,
|
||||
border: 1,
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
expectedErrors: [gl.INVALID_VALUE]},
|
||||
expectedError: gl.INVALID_VALUE},
|
||||
{target: gl.TEXTURE_2D,
|
||||
internalFormat: gl.RGBA,
|
||||
border: 0,
|
||||
format: gl.RGB,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
expectedErrors: [gl.INVALID_OPERATION]},
|
||||
expectedError: gl.INVALID_OPERATION},
|
||||
{target: gl.TEXTURE_2D,
|
||||
internalFormat: gl.RGBA,
|
||||
border: 0,
|
||||
format: gl.RGBA,
|
||||
type: gl.BYTE,
|
||||
expectedErrors: [gl.INVALID_ENUM]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
internalFormat: gl.RGBA,
|
||||
border: 0,
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
expectedErrors: [gl.NO_ERROR]} ];
|
||||
expectedError: gl.NO_ERROR} ];
|
||||
|
||||
for (var ii = 0; ii < testCases.length; ++ii)
|
||||
testTexImage2D(testCases[ii]);
|
||||
@ -221,15 +221,15 @@ testCases =
|
||||
[ {target: gl.TEXTURE_2D,
|
||||
format: 0x1903, // GL_RED
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
expectedErrors: [gl.INVALID_ENUM, gl.INVALID_OPERATION]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
format: gl.RGBA,
|
||||
type: gl.BYTE,
|
||||
expectedErrors: [gl.INVALID_ENUM, gl.INVALID_OPERATION]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
expectedErrors: [gl.NO_ERROR]} ];
|
||||
expectedError: gl.NO_ERROR} ];
|
||||
|
||||
for (var ii = 0; ii < testCases.length; ++ii)
|
||||
testTexSubImage2D(testCases[ii]);
|
||||
@ -241,19 +241,19 @@ testCases =
|
||||
[ {target: 0x0DE0, // GL_TEXTURE_1D
|
||||
pname: gl.TEXTURE_WRAP_T,
|
||||
param: gl.REPEAT,
|
||||
expectedErrors: [gl.INVALID_ENUM]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
pname: 0x813A, // GL_TEXTURE_MIN_LOD
|
||||
param: 0,
|
||||
expectedErrors: [gl.INVALID_ENUM]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
pname: gl.TEXTURE_WRAP_T,
|
||||
param: 0x2900, // GL_CLAMP
|
||||
expectedErrors: [gl.INVALID_ENUM]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
pname: gl.TEXTURE_WRAP_T,
|
||||
param: gl.REPEAT,
|
||||
expectedErrors: [gl.NO_ERROR]} ];
|
||||
expectedError: gl.NO_ERROR} ];
|
||||
|
||||
for (var ii = 0; ii < testCases.length; ++ii)
|
||||
testTexParameter(testCases[ii]);
|
||||
@ -264,13 +264,13 @@ debug("Checking GetTexParameter: a set of inputs that are valid in GL but invali
|
||||
testCases =
|
||||
[ {target: 0x0DE0, // GL_TEXTURE_1D
|
||||
pname: gl.TEXTURE_WRAP_T,
|
||||
expectedErrors: [gl.INVALID_ENUM]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
pname: 0x813A, // GL_TEXTURE_MIN_LOD
|
||||
expectedErrors: [gl.INVALID_ENUM]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
pname: gl.TEXTURE_WRAP_T,
|
||||
expectedErrors: [gl.NO_ERROR]} ];
|
||||
expectedError: gl.NO_ERROR} ];
|
||||
|
||||
for (var ii = 0; ii < testCases.length; ++ii)
|
||||
testGetTexParameter(testCases[ii]);
|
||||
@ -293,22 +293,22 @@ testCases =
|
||||
colorBufferFormat: gl.RGB565,
|
||||
internalFormat: 0x8054, // GL_RGB16
|
||||
border: 0,
|
||||
expectedErrors: [gl.INVALID_ENUM]},
|
||||
expectedError: gl.INVALID_ENUM},
|
||||
{target: gl.TEXTURE_2D,
|
||||
colorBufferFormat: gl.RGB565,
|
||||
internalFormat: gl.RGBA,
|
||||
border: 1,
|
||||
expectedErrors: [gl.INVALID_VALUE]},
|
||||
expectedError: gl.INVALID_VALUE},
|
||||
{target: gl.TEXTURE_2D,
|
||||
colorBufferFormat: gl.RGB565,
|
||||
internalFormat: gl.RGBA,
|
||||
border: 0,
|
||||
expectedErrors: [gl.INVALID_OPERATION]},
|
||||
expectedError: gl.INVALID_OPERATION},
|
||||
{target: gl.TEXTURE_2D,
|
||||
colorBufferFormat: gl.RGB565,
|
||||
internalFormat: gl.RGB,
|
||||
border: 0,
|
||||
expectedErrors: [gl.NO_ERROR]} ];
|
||||
expectedError: gl.NO_ERROR} ];
|
||||
|
||||
for (var ii = 0; ii < testCases.length; ++ii)
|
||||
testCopyTexImage2D(testCases[ii]);
|
||||
@ -320,11 +320,11 @@ testCases =
|
||||
[ {target: gl.TEXTURE_2D,
|
||||
colorBufferFormat: gl.RGB5_A1,
|
||||
internalFormat: gl.RGBA,
|
||||
expectedErrors: [gl.NO_ERROR]},
|
||||
expectedError: gl.NO_ERROR},
|
||||
{target: gl.TEXTURE_2D,
|
||||
colorBufferFormat: gl.RGB565,
|
||||
internalFormat: gl.RGBA,
|
||||
expectedErrors: [gl.INVALID_OPERATION]} ];
|
||||
expectedError: gl.INVALID_OPERATION} ];
|
||||
|
||||
for (var ii = 0; ii < testCases.length; ++ii)
|
||||
testCopyTexSubImage2D(testCases[ii]);
|
||||
@ -336,19 +336,19 @@ testCases =
|
||||
[ {contextAlpha: true,
|
||||
internalFormat: gl.RGBA,
|
||||
subImage: false,
|
||||
expectedErrors: [gl.NO_ERROR]},
|
||||
expectedError: gl.NO_ERROR},
|
||||
{contextAlpha: false,
|
||||
internalFormat: gl.RGBA,
|
||||
subImage: false,
|
||||
expectedErrors: [gl.INVALID_OPERATION]},
|
||||
expectedError: gl.INVALID_OPERATION},
|
||||
{contextAlpha: true,
|
||||
internalFormat: gl.RGBA,
|
||||
subImage: true,
|
||||
expectedErrors: [gl.NO_ERROR]},
|
||||
expectedError: gl.NO_ERROR},
|
||||
{contextAlpha: false,
|
||||
internalFormat: gl.RGBA,
|
||||
subImage: true,
|
||||
expectedErrors: [gl.INVALID_OPERATION]} ];
|
||||
expectedError: gl.INVALID_OPERATION} ];
|
||||
|
||||
for (var ii = 0; ii < testCases.length; ++ii)
|
||||
testCopyFromInternalFBO(testCases[ii]);
|
||||
|
@ -66,9 +66,9 @@ if (!gl) {
|
||||
var err = gl.getError();
|
||||
if (err == gl.NO_ERROR) {
|
||||
testFailed("should NOT be able to create texture of type " + formatName);
|
||||
} else if (err == gl.INVALID_ENUM ||
|
||||
err == gl.INVALID_OPERATION)
|
||||
{
|
||||
} else if (err == gl.INVALID_OPERATION) {
|
||||
testFailed("should return gl.INVALID_ENUM for type " + formatName);
|
||||
} else if (err == gl.INVALID_ENUM) {
|
||||
testPassed("not able to create invalid format: " + formatName);
|
||||
}
|
||||
}
|
||||
|
@ -35,10 +35,10 @@ function IsFormatValidForTex(gl, format, type) {
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, format, 4, 4, 0, format, type, null);
|
||||
|
||||
var error = gl.getError();
|
||||
if (error == gl.INVALID_ENUM || error == gl.INVALID_OPERATION)
|
||||
if (error == gl.INVALID_ENUM)
|
||||
return false;
|
||||
|
||||
ok(error == gl.NO_ERROR, 'Error should be INVALID_{ENUM,OPERATION} or NO_ERROR.');
|
||||
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
|
||||
return error == gl.NO_ERROR;
|
||||
}
|
||||
|
||||
@ -50,10 +50,10 @@ function IsFormatValidForTexFB(gl, format, type) {
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, format, 4, 4, 0, format, type, null);
|
||||
|
||||
var error = gl.getError();
|
||||
if (error == gl.INVALID_ENUM || error == gl.INVALID_OPERATION)
|
||||
if (error == gl.INVALID_ENUM)
|
||||
return false;
|
||||
|
||||
ok(error == gl.NO_ERROR, 'Error should be INVALID_{ENUM,OPERATION} or NO_ERROR.');
|
||||
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
|
||||
|
||||
var fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
@ -75,10 +75,10 @@ function IsFormatValidForTexFBRead(gl, texFormat, texType, readType) {
|
||||
null);
|
||||
|
||||
var error = gl.getError();
|
||||
if (error == gl.INVALID_ENUM || error == gl.INVALID_OPERATION)
|
||||
if (error == gl.INVALID_ENUM)
|
||||
return false;
|
||||
|
||||
ok(error == gl.NO_ERROR, 'Error should be INVALID_{ENUM,OPERATION} or NO_ERROR.');
|
||||
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
|
||||
|
||||
var fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
|
@ -478,8 +478,7 @@ skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
|
||||
[webgl/test_compressedTexImage2D.html]
|
||||
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
|
||||
[webgl/test_compressedTexSubImage2D.html]
|
||||
skip-if = true # Bug 1226336
|
||||
#skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
|
||||
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
|
||||
[webgl/test_texImage2D.html]
|
||||
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
|
||||
[webgl/test_texSubImage2D.html]
|
||||
|
@ -344,40 +344,30 @@ interface WebGL2RenderingContext : WebGLRenderingContext
|
||||
void texStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
void texStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
||||
GLsizei depth);
|
||||
|
||||
void texImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLint border, GLenum format,
|
||||
[Throws]
|
||||
void texImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLenum format,
|
||||
GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
|
||||
[Throws] // Can't actually throw.
|
||||
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type,
|
||||
(ArrayBufferView or SharedArrayBufferView)? pixels);
|
||||
[Throws] // Can't actually throw.
|
||||
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLenum format, GLenum type, ImageData? data);
|
||||
[Throws]
|
||||
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLenum format, GLenum type, HTMLImageElement image);
|
||||
[Throws]
|
||||
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLenum format, GLenum type,
|
||||
HTMLCanvasElement canvas);
|
||||
[Throws]
|
||||
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLenum format, GLenum type, HTMLVideoElement video);
|
||||
|
||||
void copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
|
||||
(ArrayBufferView or SharedArrayBufferView)? pixels);
|
||||
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLenum format, GLenum type, ImageData? data);
|
||||
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLenum format, GLenum type, HTMLImageElement image);
|
||||
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLenum format, GLenum type, HTMLCanvasElement canvas);
|
||||
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLenum format, GLenum type, HTMLVideoElement video);
|
||||
void copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||
GLsizei width, GLsizei height, GLsizei depth, GLint border,
|
||||
(ArrayBufferView or SharedArrayBufferView) data);
|
||||
void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLenum format,
|
||||
(ArrayBufferView or SharedArrayBufferView) data);
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data);
|
||||
void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data);
|
||||
|
||||
/* Programs and shaders */
|
||||
[WebGLHandlesContextLoss] GLint getFragDataLocation(WebGLProgram? program, DOMString name);
|
||||
|
@ -694,12 +694,11 @@ interface WebGLRenderingContext {
|
||||
void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
|
||||
|
||||
|
||||
// Overloads must share [Throws].
|
||||
[Throws] // Can't actually throw.
|
||||
[Throws]
|
||||
void texImage2D(GLenum target, GLint level, GLenum internalformat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||
GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
|
||||
[Throws] // Can't actually throw.
|
||||
[Throws]
|
||||
void texImage2D(GLenum target, GLint level, GLenum internalformat,
|
||||
GLenum format, GLenum type, ImageData? pixels);
|
||||
[Throws]
|
||||
@ -715,11 +714,11 @@ interface WebGLRenderingContext {
|
||||
void texParameterf(GLenum target, GLenum pname, GLfloat param);
|
||||
void texParameteri(GLenum target, GLenum pname, GLint param);
|
||||
|
||||
[Throws] // Can't actually throw.
|
||||
[Throws]
|
||||
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height, GLenum format, GLenum type,
|
||||
(ArrayBufferView or SharedArrayBufferView)? pixels);
|
||||
[Throws] // Can't actually throw.
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
|
||||
[Throws]
|
||||
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLenum format, GLenum type, ImageData? pixels);
|
||||
[Throws]
|
||||
|
20
gfx/2d/2D.h
20
gfx/2d/2D.h
@ -89,7 +89,7 @@ struct DrawOptions {
|
||||
operation is multiplied. */
|
||||
CompositionOp mCompositionOp; /**< The operator that indicates how the source and
|
||||
destination patterns are blended. */
|
||||
AntialiasMode mAntialiasMode; /**< The AntiAlias mode used for this drawing
|
||||
AntialiasMode mAntialiasMode; /**< The AntiAlias mode used for this drawing
|
||||
operation. */
|
||||
};
|
||||
|
||||
@ -415,25 +415,25 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* GetData() const
|
||||
uint8_t* GetData()
|
||||
{
|
||||
MOZ_ASSERT(mIsMapped);
|
||||
return mMap.mData;
|
||||
}
|
||||
|
||||
int32_t GetStride() const
|
||||
int32_t GetStride()
|
||||
{
|
||||
MOZ_ASSERT(mIsMapped);
|
||||
return mMap.mStride;
|
||||
}
|
||||
|
||||
const MappedSurface* GetMappedSurface() const
|
||||
MappedSurface* GetMappedSurface()
|
||||
{
|
||||
MOZ_ASSERT(mIsMapped);
|
||||
return &mMap;
|
||||
}
|
||||
|
||||
bool IsMapped() const { return mIsMapped; }
|
||||
bool IsMapped() { return mIsMapped; }
|
||||
|
||||
private:
|
||||
RefPtr<DataSourceSurface> mSurface;
|
||||
@ -527,7 +527,7 @@ class Path : public RefCounted<Path>
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(Path)
|
||||
virtual ~Path();
|
||||
|
||||
|
||||
virtual BackendType GetBackendType() const = 0;
|
||||
|
||||
/** This returns a PathBuilder object that contains a copy of the contents of
|
||||
@ -803,7 +803,7 @@ public:
|
||||
|
||||
/** @see CopySurface
|
||||
* Same as CopySurface, except uses itself as the source.
|
||||
*
|
||||
*
|
||||
* Some backends may be able to optimize this better
|
||||
* than just taking a snapshot and using CopySurface.
|
||||
*/
|
||||
@ -863,7 +863,7 @@ public:
|
||||
const Pattern &aPattern,
|
||||
const StrokeOptions &aStrokeOptions = StrokeOptions(),
|
||||
const DrawOptions &aOptions = DrawOptions()) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Fill a path on the draw target with a certain source pattern.
|
||||
*
|
||||
@ -968,7 +968,7 @@ public:
|
||||
* Create a DrawTarget that captures the drawing commands and can be replayed
|
||||
* onto a compatible DrawTarget afterwards.
|
||||
*
|
||||
* @param aSize Size of the area this DT will capture.
|
||||
* @param aSize Size of the area this DT will capture.
|
||||
*/
|
||||
virtual already_AddRefed<DrawTargetCapture> CreateCaptureDT(const IntSize& aSize);
|
||||
|
||||
@ -1170,7 +1170,7 @@ public:
|
||||
|
||||
static already_AddRefed<DrawTarget>
|
||||
CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT);
|
||||
|
||||
|
||||
static already_AddRefed<DrawTarget>
|
||||
CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace gfx {
|
||||
|
||||
uint8_t*
|
||||
DataAtOffset(DataSourceSurface* aSurface,
|
||||
const DataSourceSurface::MappedSurface* aMap,
|
||||
DataSourceSurface::MappedSurface* aMap,
|
||||
IntPoint aPoint)
|
||||
{
|
||||
if (!SurfaceContainsPoint(aSurface, aPoint)) {
|
||||
|
@ -874,8 +874,11 @@ Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
|
||||
|
||||
RefPtr<SourceSurfaceRawData> newSurf = new SourceSurfaceRawData();
|
||||
|
||||
newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false);
|
||||
return newSurf.forget();
|
||||
if (newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false)) {
|
||||
return newSurf.forget();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<DataSourceSurface>
|
||||
|
@ -12,7 +12,7 @@
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
void
|
||||
bool
|
||||
SourceSurfaceRawData::InitWrappingData(uint8_t *aData,
|
||||
const IntSize &aSize,
|
||||
int32_t aStride,
|
||||
@ -24,6 +24,8 @@ SourceSurfaceRawData::InitWrappingData(uint8_t *aData,
|
||||
mStride = aStride;
|
||||
mFormat = aFormat;
|
||||
mOwnData = aOwnData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
virtual IntSize GetSize() const override { return mSize; }
|
||||
virtual SurfaceFormat GetFormat() const override { return mFormat; }
|
||||
|
||||
void InitWrappingData(unsigned char *aData,
|
||||
bool InitWrappingData(unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
int32_t aStride,
|
||||
SurfaceFormat aFormat,
|
||||
|
@ -42,7 +42,6 @@ EXPORTS.mozilla.gfx += [
|
||||
'ScaleFactor.h',
|
||||
'ScaleFactors2D.h',
|
||||
'SourceSurfaceCairo.h',
|
||||
'SourceSurfaceRawData.h',
|
||||
'StackArray.h',
|
||||
'Tools.h',
|
||||
'Types.h',
|
||||
|
@ -141,9 +141,6 @@ GLenum TextureD3D::getBaseLevelInternalFormat() const
|
||||
|
||||
bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
|
||||
{
|
||||
if (image->isDirty())
|
||||
return false;
|
||||
|
||||
if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload)
|
||||
{
|
||||
return false;
|
||||
|
@ -505,13 +505,6 @@ gl::Error Blit9::setFormatConvertShaders(GLenum destFormat)
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsEmpty(const RECT& rect)
|
||||
{
|
||||
return rect.left == rect.right ||
|
||||
rect.top == rect.bottom;
|
||||
}
|
||||
|
||||
gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture)
|
||||
{
|
||||
ASSERT(surface);
|
||||
@ -523,10 +516,7 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
|
||||
|
||||
// Copy the render target into a texture
|
||||
IDirect3DTexture9 *texture;
|
||||
HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left,
|
||||
sourceRect.bottom - sourceRect.top, 1,
|
||||
D3DUSAGE_RENDERTARGET, sourceDesc.Format,
|
||||
D3DPOOL_DEFAULT, &texture, NULL);
|
||||
HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
@ -544,82 +534,13 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
|
||||
return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result);
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC destDesc;
|
||||
textureSurface->GetDesc(&destDesc);
|
||||
|
||||
RECT subsetSourceRect = sourceRect;
|
||||
RECT subsetDestRect = { 0, 0, destDesc.Width, destDesc.Height };
|
||||
if (sourceRect.left < 0) {
|
||||
LONG diff = 0 - sourceRect.left;
|
||||
ASSERT(diff > 0);
|
||||
subsetSourceRect.left += diff;
|
||||
subsetDestRect.left += diff;
|
||||
}
|
||||
|
||||
if (sourceRect.top < 0) {
|
||||
LONG diff = 0 - sourceRect.top;
|
||||
ASSERT(diff > 0);
|
||||
subsetSourceRect.top += diff;
|
||||
subsetDestRect.top += diff;
|
||||
}
|
||||
|
||||
if (sourceRect.right > LONG(sourceDesc.Width)) {
|
||||
LONG diff = sourceRect.right - sourceDesc.Width;
|
||||
ASSERT(diff > 0);
|
||||
subsetSourceRect.right -= diff;
|
||||
subsetDestRect.right -= diff;
|
||||
}
|
||||
|
||||
if (sourceRect.bottom > LONG(sourceDesc.Height)) {
|
||||
LONG diff = sourceRect.bottom - sourceDesc.Height;
|
||||
ASSERT(diff > 0);
|
||||
subsetSourceRect.bottom -= diff;
|
||||
subsetDestRect.bottom -= diff;
|
||||
}
|
||||
|
||||
ASSERT(subsetSourceRect.left <= subsetSourceRect.right);
|
||||
ASSERT(subsetSourceRect.top <= subsetSourceRect.bottom);
|
||||
ASSERT(subsetDestRect.left <= subsetDestRect.right);
|
||||
ASSERT(subsetDestRect.top <= subsetDestRect.bottom);
|
||||
|
||||
ASSERT(subsetSourceRect.right - subsetSourceRect.left == subsetDestRect.right - subsetDestRect.left);
|
||||
ASSERT(subsetSourceRect.bottom - subsetSourceRect.top == subsetDestRect.bottom - subsetDestRect.top);
|
||||
|
||||
mRenderer->endScene();
|
||||
|
||||
if (!IsEmpty(subsetSourceRect)) {
|
||||
result = device->StretchRect(surface, &subsetSourceRect, textureSurface, &subsetDestRect, D3DTEXF_NONE);
|
||||
}
|
||||
result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
|
||||
|
||||
SafeRelease(textureSurface);
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
if (!(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)) {
|
||||
std::printf("Bad result: 0x%x\n", result);
|
||||
|
||||
std::printf("sourceRect: %i,%i - %i,%i\n", sourceRect.left, sourceRect.top,
|
||||
sourceRect.right, sourceRect.bottom);
|
||||
|
||||
std::printf("sourceDesc: Format: %u, Type: %u, Usage: %u, Pool: %u,"
|
||||
" MSType: %u, MSQuality: %u, Width: %u, Height: %u\n",
|
||||
sourceDesc.Format, sourceDesc.Type, sourceDesc.Usage,
|
||||
sourceDesc.Pool, sourceDesc.MultiSampleType,
|
||||
sourceDesc.MultiSampleQuality, sourceDesc.Width,
|
||||
sourceDesc.Height);
|
||||
|
||||
std::printf("subsetSourceRect: %i,%i - %i,%i\n", subsetSourceRect.left, subsetSourceRect.top,
|
||||
subsetSourceRect.right, subsetSourceRect.bottom);
|
||||
|
||||
std::printf("destDesc: Format: %u, Type: %u, Usage: %u, Pool: %u, MSType: %u,"
|
||||
" MSQuality: %u, Width: %u, Height: %u\n",
|
||||
destDesc.Format, destDesc.Type, destDesc.Usage, destDesc.Pool,
|
||||
destDesc.MultiSampleType, destDesc.MultiSampleQuality,
|
||||
destDesc.Width, destDesc.Height);
|
||||
|
||||
std::printf("subsetDestRect: %i,%i - %i,%i\n", subsetDestRect.left, subsetDestRect.top,
|
||||
subsetDestRect.right, subsetDestRect.bottom);
|
||||
}
|
||||
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
|
||||
SafeRelease(texture);
|
||||
return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result);
|
||||
|
@ -934,18 +934,6 @@ GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
|
||||
return;
|
||||
}
|
||||
|
||||
DrawBlitTextureToFramebuffer(srcTex, destFB, srcSize, destSize, srcTarget,
|
||||
internalFBs);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GLBlitHelper::DrawBlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
|
||||
const gfx::IntSize& srcSize,
|
||||
const gfx::IntSize& destSize,
|
||||
GLenum srcTarget,
|
||||
bool internalFBs)
|
||||
{
|
||||
BlitType type;
|
||||
switch (srcTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
|
@ -143,11 +143,6 @@ public:
|
||||
const gfx::IntSize& destSize,
|
||||
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
|
||||
bool internalFBs = false);
|
||||
void DrawBlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
|
||||
const gfx::IntSize& srcSize,
|
||||
const gfx::IntSize& destSize,
|
||||
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
|
||||
bool internalFBs = false);
|
||||
void BlitFramebufferToTexture(GLuint srcFB, GLuint destTex,
|
||||
const gfx::IntSize& srcSize,
|
||||
const gfx::IntSize& destSize,
|
||||
|
@ -647,11 +647,7 @@ public:
|
||||
MOZ_ASSERT(!mHasBeenChecked);
|
||||
mHasBeenChecked = true;
|
||||
|
||||
const GLenum ret = mGL.fGetError();
|
||||
|
||||
while (mGL.fGetError()) {}
|
||||
|
||||
return ret;
|
||||
return mGL.fGetError();
|
||||
}
|
||||
|
||||
~LocalErrorScope() {
|
||||
@ -2313,7 +2309,6 @@ public:
|
||||
public:
|
||||
void fDrawBuffers(GLsizei n, const GLenum* bufs) {
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fDrawBuffers);
|
||||
mSymbols.fDrawBuffers(n, bufs);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
@ -836,15 +836,6 @@ GLContext::InitFeatures()
|
||||
}
|
||||
}
|
||||
|
||||
if (ShouldDumpExts()) {
|
||||
for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax); featureId++) {
|
||||
GLFeature feature = GLFeature(featureId);
|
||||
printf_stderr("[%s] Feature::%s\n",
|
||||
IsSupported(feature) ? "enabled" : "disabled",
|
||||
GetFeatureName(feature));
|
||||
}
|
||||
}
|
||||
|
||||
if (WorkAroundDriverBugs()) {
|
||||
#ifdef XP_MACOSX
|
||||
// MacOSX 10.6 reports to support EXT_framebuffer_sRGB and EXT_texture_sRGB but
|
||||
|
@ -114,7 +114,6 @@ GLContextCGL::MakeCurrentImpl(bool aForce)
|
||||
|
||||
if (mContext) {
|
||||
[mContext makeCurrentContext];
|
||||
MOZ_ASSERT(IsCurrent());
|
||||
// Use non-blocking swap in "ASAP mode".
|
||||
// ASAP mode means that rendering is iterated as fast as possible.
|
||||
// ASAP mode is entered when layout.frame_rate=0 (requires restart).
|
||||
|
@ -174,56 +174,34 @@ ScopedRenderbuffer::UnwrapImpl()
|
||||
}
|
||||
|
||||
/* ScopedBindTexture **********************************************************/
|
||||
|
||||
static GLuint
|
||||
GetBoundTexture(GLContext* gl, GLenum texTarget)
|
||||
void
|
||||
ScopedBindTexture::Init(GLenum aTarget)
|
||||
{
|
||||
GLenum bindingTarget;
|
||||
switch (texTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
bindingTarget = LOCAL_GL_TEXTURE_BINDING_2D;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP:
|
||||
bindingTarget = LOCAL_GL_TEXTURE_BINDING_CUBE_MAP;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
bindingTarget = LOCAL_GL_TEXTURE_BINDING_3D;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
bindingTarget = LOCAL_GL_TEXTURE_BINDING_2D_ARRAY;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_RECTANGLE_ARB:
|
||||
bindingTarget = LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_EXTERNAL:
|
||||
bindingTarget = LOCAL_GL_TEXTURE_BINDING_EXTERNAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("bad texTarget");
|
||||
}
|
||||
|
||||
GLuint ret = 0;
|
||||
gl->GetUIntegerv(bindingTarget, &ret);
|
||||
return ret;
|
||||
mTarget = aTarget;
|
||||
mOldTex = 0;
|
||||
GLenum bindingTarget = (aTarget == LOCAL_GL_TEXTURE_2D) ? LOCAL_GL_TEXTURE_BINDING_2D
|
||||
: (aTarget == LOCAL_GL_TEXTURE_3D) ? LOCAL_GL_TEXTURE_BINDING_3D
|
||||
: (aTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) ? LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB
|
||||
: (aTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? LOCAL_GL_TEXTURE_BINDING_CUBE_MAP
|
||||
: (aTarget == LOCAL_GL_TEXTURE_EXTERNAL) ? LOCAL_GL_TEXTURE_BINDING_EXTERNAL
|
||||
: LOCAL_GL_NONE;
|
||||
MOZ_ASSERT(bindingTarget != LOCAL_GL_NONE);
|
||||
mGL->GetUIntegerv(bindingTarget, &mOldTex);
|
||||
}
|
||||
|
||||
ScopedBindTexture::ScopedBindTexture(GLContext* aGL, GLuint aNewTex, GLenum aTarget)
|
||||
: ScopedGLWrapper<ScopedBindTexture>(aGL)
|
||||
, mTarget(aTarget)
|
||||
, mOldTex(GetBoundTexture(aGL, aTarget))
|
||||
{
|
||||
mGL->fBindTexture(mTarget, aNewTex);
|
||||
}
|
||||
{
|
||||
Init(aTarget);
|
||||
mGL->fBindTexture(aTarget, aNewTex);
|
||||
}
|
||||
|
||||
void
|
||||
ScopedBindTexture::UnwrapImpl()
|
||||
{
|
||||
// Check that we're not falling out of scope after the current context changed.
|
||||
MOZ_ASSERT(mGL->IsCurrent());
|
||||
|
||||
mGL->fBindTexture(mTarget, mOldTex);
|
||||
}
|
||||
|
||||
@ -336,16 +314,16 @@ ScopedViewportRect::ScopedViewportRect(GLContext* aGL,
|
||||
GLsizei width, GLsizei height)
|
||||
: ScopedGLWrapper<ScopedViewportRect>(aGL)
|
||||
{
|
||||
mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, mSavedViewportRect);
|
||||
mGL->fViewport(x, y, width, height);
|
||||
mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, mSavedViewportRect);
|
||||
mGL->fViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
void ScopedViewportRect::UnwrapImpl()
|
||||
{
|
||||
mGL->fViewport(mSavedViewportRect[0],
|
||||
mSavedViewportRect[1],
|
||||
mSavedViewportRect[2],
|
||||
mSavedViewportRect[3]);
|
||||
mGL->fViewport(mSavedViewportRect[0],
|
||||
mSavedViewportRect[1],
|
||||
mSavedViewportRect[2],
|
||||
mSavedViewportRect[3]);
|
||||
}
|
||||
|
||||
/* ScopedScissorRect **********************************************************/
|
||||
@ -355,22 +333,22 @@ ScopedScissorRect::ScopedScissorRect(GLContext* aGL,
|
||||
GLsizei width, GLsizei height)
|
||||
: ScopedGLWrapper<ScopedScissorRect>(aGL)
|
||||
{
|
||||
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
|
||||
mGL->fScissor(x, y, width, height);
|
||||
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
|
||||
mGL->fScissor(x, y, width, height);
|
||||
}
|
||||
|
||||
ScopedScissorRect::ScopedScissorRect(GLContext* aGL)
|
||||
: ScopedGLWrapper<ScopedScissorRect>(aGL)
|
||||
{
|
||||
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
|
||||
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
|
||||
}
|
||||
|
||||
void ScopedScissorRect::UnwrapImpl()
|
||||
{
|
||||
mGL->fScissor(mSavedScissorRect[0],
|
||||
mSavedScissorRect[1],
|
||||
mSavedScissorRect[2],
|
||||
mSavedScissorRect[3]);
|
||||
mGL->fScissor(mSavedScissorRect[0],
|
||||
mSavedScissorRect[1],
|
||||
mSavedScissorRect[2],
|
||||
mSavedScissorRect[3]);
|
||||
}
|
||||
|
||||
/* ScopedVertexAttribPointer **************************************************/
|
||||
@ -481,8 +459,6 @@ ScopedGLDrawState::ScopedGLDrawState(GLContext* aGL)
|
||||
|
||||
ScopedGLDrawState::~ScopedGLDrawState()
|
||||
{
|
||||
MOZ_ASSERT(mGL->IsCurrent());
|
||||
|
||||
mGL->fScissor(scissorBox[0], scissorBox[1],
|
||||
scissorBox[2], scissorBox[3]);
|
||||
|
||||
@ -548,31 +524,5 @@ ScopedPackAlignment::UnwrapImpl() {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// ScopedUnpackAlignment
|
||||
|
||||
ScopedUnpackAlignment::ScopedUnpackAlignment(GLContext* gl, GLint scopedVal)
|
||||
: ScopedGLWrapper<ScopedUnpackAlignment>(gl)
|
||||
{
|
||||
MOZ_ASSERT(scopedVal == 1 ||
|
||||
scopedVal == 2 ||
|
||||
scopedVal == 4 ||
|
||||
scopedVal == 8);
|
||||
|
||||
gl->fGetIntegerv(LOCAL_GL_UNPACK_ALIGNMENT, &mOldVal);
|
||||
|
||||
if (scopedVal != mOldVal) {
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, scopedVal);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScopedUnpackAlignment::UnwrapImpl() {
|
||||
// Check that we're not falling out of scope after the current context changed.
|
||||
MOZ_ASSERT(mGL->IsCurrent());
|
||||
|
||||
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mOldVal);
|
||||
}
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
@ -45,7 +45,6 @@ protected:
|
||||
public:
|
||||
void Unwrap() {
|
||||
MOZ_ASSERT(!mIsUnwrapped);
|
||||
MOZ_ASSERT(IsContextCurrent(mGL));
|
||||
|
||||
Derived* derived = static_cast<Derived*>(this);
|
||||
derived->UnwrapImpl();
|
||||
@ -169,8 +168,11 @@ struct ScopedBindTexture
|
||||
friend struct ScopedGLWrapper<ScopedBindTexture>;
|
||||
|
||||
protected:
|
||||
const GLenum mTarget;
|
||||
const GLuint mOldTex;
|
||||
GLuint mOldTex;
|
||||
GLenum mTarget;
|
||||
|
||||
private:
|
||||
void Init(GLenum aTarget);
|
||||
|
||||
public:
|
||||
ScopedBindTexture(GLContext* aGL, GLuint aNewTex,
|
||||
@ -356,23 +358,6 @@ public:
|
||||
protected:
|
||||
void UnwrapImpl();
|
||||
};
|
||||
|
||||
|
||||
struct ScopedUnpackAlignment
|
||||
: public ScopedGLWrapper<ScopedUnpackAlignment>
|
||||
{
|
||||
friend struct ScopedGLWrapper<ScopedUnpackAlignment>;
|
||||
|
||||
protected:
|
||||
GLint mOldVal;
|
||||
|
||||
public:
|
||||
ScopedUnpackAlignment(GLContext* gl, GLint scopedVal);
|
||||
|
||||
protected:
|
||||
void UnwrapImpl();
|
||||
};
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
@ -414,9 +414,6 @@ private:
|
||||
|
||||
DECL_GFX_PREF(Live, "webgl.disable-fail-if-major-performance-caveat",
|
||||
WebGLDisableFailIfMajorPerformanceCaveat, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.disable-DOM-blit-uploads",
|
||||
WebGLDisableDOMBlitUploads, bool, false);
|
||||
|
||||
DECL_GFX_PREF(Live, "webgl.disabled", WebGLDisabled, bool, false);
|
||||
|
||||
DECL_GFX_PREF(Live, "webgl.enable-draft-extensions", WebGLDraftExtensionsEnabled, bool, false);
|
||||
@ -430,8 +427,6 @@ private:
|
||||
DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.restore-context-when-visible", WebGLRestoreWhenVisible, bool, true);
|
||||
|
||||
DECL_GFX_PREF(Live, "webgl.webgl2-compat-mode", WebGL2CompatMode, bool, false);
|
||||
|
||||
// WARNING:
|
||||
// Please make sure that you've added your new preference to the list above in alphabetical order.
|
||||
// Please do not just append it to the end of the list.
|
||||
|
@ -4787,7 +4787,7 @@ nsImageRenderer::PrepareImage()
|
||||
// prefer SurfaceFromElement as it's more reliable.
|
||||
mImageElementSurface =
|
||||
nsLayoutUtils::SurfaceFromElement(property->GetReferencedElement());
|
||||
if (!mImageElementSurface.GetSourceSurface()) {
|
||||
if (!mImageElementSurface.mSourceSurface) {
|
||||
mPaintServerFrame = property->GetReferencedFrame();
|
||||
if (!mPaintServerFrame) {
|
||||
mPrepareResult = DrawResult::BAD_IMAGE;
|
||||
@ -4872,8 +4872,7 @@ nsImageRenderer::ComputeIntrinsicSize()
|
||||
appUnitsPerDevPixel));
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(mImageElementSurface.GetSourceSurface(),
|
||||
"Surface should be ready.");
|
||||
NS_ASSERTION(mImageElementSurface.mSourceSurface, "Surface should be ready.");
|
||||
IntSize surfaceSize = mImageElementSurface.mSize;
|
||||
result.SetSize(
|
||||
nsSize(nsPresContext::CSSPixelsToAppUnits(surfaceSize.width),
|
||||
@ -5114,9 +5113,9 @@ nsImageRenderer::DrawableForElement(const nsRect& aImageRect,
|
||||
|
||||
return drawable.forget();
|
||||
}
|
||||
NS_ASSERTION(mImageElementSurface.GetSourceSurface(), "Surface should be ready.");
|
||||
NS_ASSERTION(mImageElementSurface.mSourceSurface, "Surface should be ready.");
|
||||
RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(
|
||||
mImageElementSurface.GetSourceSurface().get(),
|
||||
mImageElementSurface.mSourceSurface,
|
||||
mImageElementSurface.mSize);
|
||||
return drawable.forget();
|
||||
}
|
||||
|
@ -1137,7 +1137,7 @@ public:
|
||||
* edge of the presshell area. The aPoint, aScreenRect and aFlags arguments
|
||||
* function in a similar manner as RenderSelection.
|
||||
*/
|
||||
virtual already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
virtual already_AddRefed<SourceSurface>
|
||||
RenderNode(nsIDOMNode* aNode,
|
||||
nsIntRegion* aRegion,
|
||||
nsIntPoint& aPoint,
|
||||
@ -1160,7 +1160,7 @@ public:
|
||||
* point isn't used because the position can be determined from the displayed
|
||||
* frames.
|
||||
*/
|
||||
virtual already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
virtual already_AddRefed<SourceSurface>
|
||||
RenderSelection(nsISelection* aSelection,
|
||||
nsIntPoint& aPoint,
|
||||
nsIntRect* aScreenRect,
|
||||
@ -1279,7 +1279,7 @@ public:
|
||||
nsCOMPtr<nsIContent> mOverrideContent;
|
||||
bool mReleaseContent;
|
||||
bool mPrimaryState;
|
||||
|
||||
|
||||
explicit PointerCaptureInfo(nsIContent* aPendingContent, bool aPrimaryState) :
|
||||
mPendingContent(aPendingContent), mReleaseContent(false), mPrimaryState(aPrimaryState)
|
||||
{
|
||||
|
@ -7176,23 +7176,20 @@ nsLayoutUtils::SurfaceFromElement(HTMLVideoElement* aElement,
|
||||
if (!principal)
|
||||
return result;
|
||||
|
||||
ImageContainer* container = aElement->GetImageContainer();
|
||||
ImageContainer *container = aElement->GetImageContainer();
|
||||
if (!container)
|
||||
return result;
|
||||
|
||||
AutoLockImage lockImage(container);
|
||||
|
||||
result.mLayersImage = lockImage.GetImage();
|
||||
if (!result.mLayersImage)
|
||||
layers::Image* image = lockImage.GetImage();
|
||||
if (!image) {
|
||||
return result;
|
||||
}
|
||||
result.mSourceSurface = image->GetAsSourceSurface();
|
||||
if (!result.mSourceSurface)
|
||||
return result;
|
||||
|
||||
if (aTarget) {
|
||||
// They gave us a DrawTarget to optimize for, so even though we have a layers::Image,
|
||||
// we should unconditionally grab a SourceSurface and try to optimize it.
|
||||
result.mSourceSurface = result.mLayersImage->GetAsSourceSurface();
|
||||
if (!result.mSourceSurface)
|
||||
return result;
|
||||
|
||||
RefPtr<SourceSurface> opt = aTarget->OptimizeSourceSurface(result.mSourceSurface);
|
||||
if (opt) {
|
||||
result.mSourceSurface = opt;
|
||||
@ -7201,7 +7198,7 @@ nsLayoutUtils::SurfaceFromElement(HTMLVideoElement* aElement,
|
||||
|
||||
result.mCORSUsed = aElement->GetCORSMode() != CORS_NONE;
|
||||
result.mHasSize = true;
|
||||
result.mSize = result.mLayersImage->GetSize();
|
||||
result.mSize = image->GetSize();
|
||||
result.mPrincipal = principal.forget();
|
||||
result.mIsWriteOnly = false;
|
||||
|
||||
@ -8273,9 +8270,6 @@ nsLayoutUtils::IsAPZTestLoggingEnabled()
|
||||
return gfxPrefs::APZTestLoggingEnabled();
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// SurfaceFromElementResult
|
||||
|
||||
nsLayoutUtils::SurfaceFromElementResult::SurfaceFromElementResult()
|
||||
// Use safe default values here
|
||||
: mIsWriteOnly(true)
|
||||
@ -8286,18 +8280,6 @@ nsLayoutUtils::SurfaceFromElementResult::SurfaceFromElementResult()
|
||||
{
|
||||
}
|
||||
|
||||
const RefPtr<mozilla::gfx::SourceSurface>&
|
||||
nsLayoutUtils::SurfaceFromElementResult::GetSourceSurface()
|
||||
{
|
||||
if (!mSourceSurface && mLayersImage) {
|
||||
mSourceSurface = mLayersImage->GetAsSourceSurface();
|
||||
}
|
||||
|
||||
return mSourceSurface;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
bool
|
||||
nsLayoutUtils::IsNonWrapperBlock(nsIFrame* aFrame)
|
||||
{
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "Units.h"
|
||||
#include "mozilla/ToString.h"
|
||||
#include "nsHTMLReflowMetrics.h"
|
||||
#include "ImageContainer.h"
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
@ -68,7 +67,6 @@ struct IntrinsicSize;
|
||||
struct ContainerLayerParameters;
|
||||
class WritingMode;
|
||||
namespace dom {
|
||||
class CanvasRenderingContext2D;
|
||||
class DOMRectList;
|
||||
class Element;
|
||||
class HTMLImageElement;
|
||||
@ -80,7 +78,6 @@ namespace gfx {
|
||||
struct RectCornerRadii;
|
||||
} // namespace gfx
|
||||
namespace layers {
|
||||
class Image;
|
||||
class Layer;
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
@ -2101,25 +2098,10 @@ public:
|
||||
};
|
||||
|
||||
struct SurfaceFromElementResult {
|
||||
friend class mozilla::dom::CanvasRenderingContext2D;
|
||||
friend class nsLayoutUtils;
|
||||
SurfaceFromElementResult();
|
||||
|
||||
/* If SFEResult contains a valid surface, it either mLayersImage or mSourceSurface
|
||||
* will be non-null, and GetSourceSurface() will not be null.
|
||||
*
|
||||
* For valid surfaces, mSourceSurface may be null if mLayersImage is non-null, but
|
||||
* GetSourceSurface() will create mSourceSurface from mLayersImage when called.
|
||||
*/
|
||||
|
||||
/* Video elements (at least) often are already decoded as layers::Images. */
|
||||
RefPtr<mozilla::layers::Image> mLayersImage;
|
||||
|
||||
protected:
|
||||
/* GetSourceSurface() fills this and returns its non-null value if this SFEResult
|
||||
* was successful. */
|
||||
RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
|
||||
|
||||
public:
|
||||
/* mSourceSurface will contain the resulting surface, or will be nullptr on error */
|
||||
RefPtr<SourceSurface> mSourceSurface;
|
||||
/* Contains info for drawing when there is no mSourceSurface. */
|
||||
DirectDrawInfo mDrawInfo;
|
||||
|
||||
@ -2141,13 +2123,6 @@ public:
|
||||
bool mCORSUsed;
|
||||
/* Whether the returned image contains premultiplied pixel data */
|
||||
bool mIsPremultiplied;
|
||||
|
||||
// Methods:
|
||||
|
||||
SurfaceFromElementResult();
|
||||
|
||||
// Gets mSourceSurface, or makes a SourceSurface from mLayersImage.
|
||||
const RefPtr<mozilla::gfx::SourceSurface>& GetSourceSurface();
|
||||
};
|
||||
|
||||
static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::Element *aElement,
|
||||
@ -2672,7 +2647,7 @@ public:
|
||||
|
||||
/**
|
||||
* Log a key/value pair for APZ testing during a paint.
|
||||
* @param aManager The data will be written to the APZTestData associated
|
||||
* @param aManager The data will be written to the APZTestData associated
|
||||
* with this layer manager.
|
||||
* @param aScrollId Identifies the scroll frame to which the data pertains.
|
||||
* @param aKey The key under which to log the data.
|
||||
|
@ -4202,8 +4202,6 @@ pref("webgl.enable-privileged-extensions", false);
|
||||
pref("webgl.bypass-shader-validation", false);
|
||||
pref("webgl.enable-prototype-webgl2", false);
|
||||
pref("webgl.disable-fail-if-major-performance-caveat", false);
|
||||
pref("webgl.disable-DOM-blit-uploads", false);
|
||||
pref("webgl.webgl2-compat-mode", false);
|
||||
|
||||
#ifdef RELEASE_BUILD
|
||||
// Keep this disabled on Release and Beta for now. (see bug 1171228)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user