зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1303879 - Refactor framebuffer funcs and completeness caching. - r=mtseng
MozReview-Commit-ID: Hi3uEwpmWF4
This commit is contained in:
Родитель
5ca4e283fa
Коммит
15fd350886
|
@ -13,71 +13,6 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
static bool
|
||||
GetFBInfoForBlit(const WebGLFramebuffer* fb, 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)
|
||||
{
|
||||
*out_samples = 0;
|
||||
*out_colorFormat = nullptr;
|
||||
*out_depthFormat = nullptr;
|
||||
*out_stencilFormat = nullptr;
|
||||
|
||||
if (fb->ColorAttachment(0).IsDefined()) {
|
||||
const auto& attachment = fb->ColorAttachment(0);
|
||||
*out_samples = attachment.Samples();
|
||||
*out_colorFormat = attachment.Format()->format;
|
||||
}
|
||||
|
||||
if (fb->DepthStencilAttachment().IsDefined()) {
|
||||
const auto& attachment = fb->DepthStencilAttachment();
|
||||
*out_samples = attachment.Samples();
|
||||
|
||||
*out_depthFormat = attachment.Format()->format;
|
||||
*out_stencilFormat = *out_depthFormat;
|
||||
} else {
|
||||
if (fb->DepthAttachment().IsDefined()) {
|
||||
const auto& attachment = fb->DepthAttachment();
|
||||
*out_samples = attachment.Samples();
|
||||
*out_depthFormat = attachment.Format()->format;
|
||||
}
|
||||
|
||||
if (fb->StencilAttachment().IsDefined()) {
|
||||
const auto& attachment = fb->StencilAttachment();
|
||||
*out_samples = attachment.Samples();
|
||||
*out_stencilFormat = attachment.Format()->format;
|
||||
}
|
||||
}
|
||||
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,
|
||||
|
@ -103,238 +38,41 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
|
|||
return;
|
||||
}
|
||||
|
||||
const GLbitfield depthAndStencilBits = LOCAL_GL_DEPTH_BUFFER_BIT |
|
||||
LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
if (mask & depthAndStencilBits &&
|
||||
filter != LOCAL_GL_NEAREST)
|
||||
////
|
||||
|
||||
const auto& readFB = mBoundReadFramebuffer;
|
||||
if (readFB &&
|
||||
!readFB->ValidateAndInitAttachments("blitFramebuffer's READ_FRAMEBUFFER"))
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: DEPTH_BUFFER_BIT and"
|
||||
" STENCIL_BUFFER_BIT can only be used with"
|
||||
" NEAREST filtering.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBoundReadFramebuffer == mBoundDrawFramebuffer) {
|
||||
// TODO: It's actually more complicated than this. We need to check that
|
||||
// the underlying buffers are not the same, not the framebuffers
|
||||
// themselves.
|
||||
ErrorInvalidOperation("blitFramebuffer: Source and destination must"
|
||||
" differ.");
|
||||
return;
|
||||
}
|
||||
|
||||
GLsizei srcSamples;
|
||||
const webgl::FormatInfo* srcColorFormat = nullptr;
|
||||
const webgl::FormatInfo* srcDepthFormat = nullptr;
|
||||
const webgl::FormatInfo* srcStencilFormat = nullptr;
|
||||
|
||||
if (mBoundReadFramebuffer) {
|
||||
if (!mBoundReadFramebuffer->ValidateAndInitAttachments("blitFramebuffer's READ_FRAMEBUFFER"))
|
||||
return;
|
||||
|
||||
if (!GetFBInfoForBlit(mBoundReadFramebuffer, "READ_FRAMEBUFFER", &srcSamples,
|
||||
&srcColorFormat, &srcDepthFormat, &srcStencilFormat))
|
||||
{
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
srcSamples = 0; // Always 0.
|
||||
|
||||
GetBackbufferFormats(mOptions, &srcColorFormat, &srcDepthFormat,
|
||||
&srcStencilFormat);
|
||||
}
|
||||
|
||||
GLsizei dstSamples;
|
||||
const webgl::FormatInfo* dstColorFormat = nullptr;
|
||||
const webgl::FormatInfo* dstDepthFormat = nullptr;
|
||||
const webgl::FormatInfo* dstStencilFormat = nullptr;
|
||||
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments("blitFramebuffer's DRAW_FRAMEBUFFER"))
|
||||
return;
|
||||
|
||||
if (!GetFBInfoForBlit(mBoundDrawFramebuffer, "DRAW_FRAMEBUFFER", &dstSamples,
|
||||
&dstColorFormat, &dstDepthFormat, &dstStencilFormat))
|
||||
{
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
dstSamples = gl->Screen()->Samples();
|
||||
|
||||
GetBackbufferFormats(mOptions, &dstColorFormat, &dstDepthFormat,
|
||||
&dstStencilFormat);
|
||||
}
|
||||
|
||||
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"
|
||||
" mismatch.");
|
||||
return;
|
||||
}
|
||||
|
||||
const bool srcIsInt = (srcType == webgl::ComponentType::Int);
|
||||
if (srcIsInt && filter != LOCAL_GL_NEAREST) {
|
||||
ErrorInvalidOperation("blitFramebuffer: Integer read buffers can only"
|
||||
" be filtered with NEAREST.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* GLES 3.0.4, p199:
|
||||
* Calling BlitFramebuffer will result in an INVALID_OPERATION error if
|
||||
* mask includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT, and the source
|
||||
* and destination depth and stencil buffer formats do not match.
|
||||
*
|
||||
* jgilbert: The wording is such that if only DEPTH_BUFFER_BIT is specified,
|
||||
* the stencil formats must match. This seems wrong. It could be a spec bug,
|
||||
* or I could be missing an interaction in one of the earlier paragraphs.
|
||||
*/
|
||||
if (mask & LOCAL_GL_DEPTH_BUFFER_BIT &&
|
||||
dstDepthFormat != srcDepthFormat)
|
||||
const auto& drawFB = mBoundDrawFramebuffer;
|
||||
if (drawFB &&
|
||||
!drawFB->ValidateAndInitAttachments("blitFramebuffer's DRAW_FRAMEBUFFER"))
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: Depth buffer formats must match"
|
||||
" if selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask & LOCAL_GL_STENCIL_BUFFER_BIT &&
|
||||
dstStencilFormat != srcStencilFormat)
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: Stencil buffer formats must"
|
||||
" match if selected.");
|
||||
return;
|
||||
}
|
||||
////
|
||||
|
||||
if (dstSamples != 0) {
|
||||
ErrorInvalidOperation("blitFramebuffer: DRAW_FRAMEBUFFER may not have"
|
||||
" multiple samples.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (srcSamples != 0) {
|
||||
if (mask & LOCAL_GL_COLOR_BUFFER_BIT &&
|
||||
dstColorFormat != srcColorFormat)
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: Color buffer formats must"
|
||||
" match if selected, when reading from a"
|
||||
" multisampled source.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dstX0 != srcX0 ||
|
||||
dstX1 != srcX1 ||
|
||||
dstY0 != srcY0 ||
|
||||
dstY1 != srcY1)
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: If the source is"
|
||||
" multisampled, then the source and dest"
|
||||
" regions must match exactly.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1,
|
||||
mask, filter);
|
||||
}
|
||||
|
||||
static bool
|
||||
ValidateTextureLayerAttachment(GLenum attachment)
|
||||
{
|
||||
if (LOCAL_GL_COLOR_ATTACHMENT0 <= attachment &&
|
||||
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
WebGLFramebuffer::BlitFramebuffer(this,
|
||||
readFB, srcX0, srcY0, srcX1, srcY1,
|
||||
drawFB, dstX0, dstY0, dstX1, dstY1,
|
||||
mask, filter);
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
|
||||
WebGLTexture* texture, GLint level, GLint layer)
|
||||
{
|
||||
const char funcName[] = "framebufferTextureLayer";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateFramebufferTarget(target, "framebufferTextureLayer"))
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
return;
|
||||
|
||||
if (!ValidateTextureLayerAttachment(attachment))
|
||||
return ErrorInvalidEnumInfo("framebufferTextureLayer: attachment:", attachment);
|
||||
|
||||
if (texture) {
|
||||
if (texture->IsDeleted()) {
|
||||
return ErrorInvalidValue("framebufferTextureLayer: texture must be a valid "
|
||||
"texture object.");
|
||||
}
|
||||
|
||||
if (layer < 0)
|
||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be >= 0.");
|
||||
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("framebufferTextureLayer: level must be >= 0.");
|
||||
|
||||
switch (texture->Target().get()) {
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
if (uint32_t(layer) >= mImplMax3DTextureSize) {
|
||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
|
||||
"MAX_3D_TEXTURE_SIZE");
|
||||
}
|
||||
|
||||
if (uint32_t(level) > FloorLog2(mImplMax3DTextureSize)) {
|
||||
return ErrorInvalidValue("framebufferTextureLayer: layer mube be <= "
|
||||
"log2(MAX_3D_TEXTURE_SIZE");
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
if (uint32_t(layer) >= mImplMaxArrayTextureLayers) {
|
||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
|
||||
"MAX_ARRAY_TEXTURE_LAYERS");
|
||||
}
|
||||
|
||||
if (uint32_t(level) > FloorLog2(mImplMaxTextureSize)) {
|
||||
return ErrorInvalidValue("framebufferTextureLayer: layer mube be <= "
|
||||
"log2(MAX_TEXTURE_SIZE");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return ErrorInvalidOperation("framebufferTextureLayer: texture must be an "
|
||||
"existing 3D texture, or a 2D texture array.");
|
||||
}
|
||||
}
|
||||
|
||||
WebGLFramebuffer* fb;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
|
@ -350,12 +88,10 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
|
|||
MOZ_CRASH("GFX: Bad target.");
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
return ErrorInvalidOperation("framebufferTextureLayer: cannot modify"
|
||||
" framebuffer 0.");
|
||||
}
|
||||
if (!fb)
|
||||
return ErrorInvalidOperation("%a: Xannot modify framebuffer 0.");
|
||||
|
||||
fb->FramebufferTextureLayer(attachment, texture, level, layer);
|
||||
fb->FramebufferTextureLayer(funcName, attachment, texture, level, layer);
|
||||
}
|
||||
|
||||
JS::Value
|
||||
|
@ -532,32 +268,12 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
|
|||
void
|
||||
WebGL2Context::ReadBuffer(GLenum mode)
|
||||
{
|
||||
const char funcName[] = "readBuffer";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
const bool isColorAttachment = (mode >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mode <= LastColorAttachmentEnum());
|
||||
|
||||
if (mode != LOCAL_GL_NONE && mode != LOCAL_GL_BACK && !isColorAttachment) {
|
||||
ErrorInvalidEnum("readBuffer: `mode` must be one of NONE, BACK, or "
|
||||
"COLOR_ATTACHMENTi. Was %s",
|
||||
EnumName(mode));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBoundReadFramebuffer) {
|
||||
if (mode != LOCAL_GL_NONE &&
|
||||
!isColorAttachment)
|
||||
{
|
||||
ErrorInvalidOperation("readBuffer: If READ_FRAMEBUFFER is non-null, `mode` "
|
||||
"must be COLOR_ATTACHMENTi or NONE. Was %s",
|
||||
EnumName(mode));
|
||||
return;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
mBoundReadFramebuffer->SetReadBufferMode(mode);
|
||||
gl->fReadBuffer(mode);
|
||||
mBoundReadFramebuffer->ReadBuffer(funcName, mode);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -565,9 +281,9 @@ WebGL2Context::ReadBuffer(GLenum mode)
|
|||
if (mode != LOCAL_GL_NONE &&
|
||||
mode != LOCAL_GL_BACK)
|
||||
{
|
||||
ErrorInvalidOperation("readBuffer: If READ_FRAMEBUFFER is null, `mode`"
|
||||
" must be BACK or NONE. Was %s",
|
||||
EnumName(mode));
|
||||
ErrorInvalidOperation("%s: If READ_FRAMEBUFFER is null, `mode` must be BACK or"
|
||||
" NONE. Was %s",
|
||||
funcName, EnumName(mode));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,13 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
|||
|
||||
/* GLenum */
|
||||
case LOCAL_GL_READ_BUFFER: {
|
||||
if (mBoundReadFramebuffer)
|
||||
return JS::Int32Value(mBoundReadFramebuffer->ReadBufferMode());
|
||||
if (!mBoundReadFramebuffer)
|
||||
return JS::Int32Value(gl->Screen()->GetReadBufferMode());
|
||||
|
||||
return JS::Int32Value(LOCAL_GL_BACK);
|
||||
if (!mBoundReadFramebuffer->ColorReadBuffer())
|
||||
return JS::Int32Value(LOCAL_GL_NONE);
|
||||
|
||||
return JS::Int32Value(mBoundReadFramebuffer->ColorReadBuffer()->mAttachmentPoint);
|
||||
}
|
||||
|
||||
case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
|
||||
|
|
|
@ -1637,21 +1637,11 @@ WebGLContext::DummyReadFramebufferOperation(const char* funcName)
|
|||
if (!mBoundReadFramebuffer)
|
||||
return; // Infallible.
|
||||
|
||||
const auto target = (IsWebGL2() ? LOCAL_GL_READ_FRAMEBUFFER
|
||||
: LOCAL_GL_FRAMEBUFFER);
|
||||
nsCString fbStatusInfo;
|
||||
const auto status = mBoundReadFramebuffer->CheckFramebufferStatus(target,
|
||||
&fbStatusInfo);
|
||||
const auto status = mBoundReadFramebuffer->CheckFramebufferStatus(funcName);
|
||||
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
nsCString errorText("Incomplete framebuffer");
|
||||
|
||||
if (fbStatusInfo.Length()) {
|
||||
errorText += ": ";
|
||||
errorText += fbStatusInfo;
|
||||
}
|
||||
|
||||
ErrorInvalidFramebufferOperation("%s: %s.", funcName, errorText.BeginReading());
|
||||
ErrorInvalidFramebufferOperation("%s: Framebuffer must be complete.",
|
||||
funcName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1138,6 +1138,8 @@ public:
|
|||
return LOCAL_GL_COLOR_ATTACHMENT0 + mImplMaxColorAttachments - 1;
|
||||
}
|
||||
|
||||
const decltype(mOptions)& Options() const { return mOptions; }
|
||||
|
||||
protected:
|
||||
|
||||
// Texture sizes are often not actually the GL values. Let's be explicit that these
|
||||
|
|
|
@ -101,10 +101,10 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
|
|||
return;
|
||||
}
|
||||
|
||||
std::vector<const WebGLFBAttachPoint*> fbAttachments;
|
||||
if (mWebGL->mBoundDrawFramebuffer) {
|
||||
const auto& fb = mWebGL->mBoundDrawFramebuffer;
|
||||
fb->GatherAttachments(&fbAttachments);
|
||||
const std::vector<const WebGLFBAttachPoint*>* attachList = nullptr;
|
||||
const auto& fb = mWebGL->mBoundDrawFramebuffer;
|
||||
if (fb) {
|
||||
attachList = &(fb->ResolvedCompleteData()->texDrawBuffers);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mWebGL->mActiveProgramLinkInfo);
|
||||
|
@ -120,7 +120,9 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
|
|||
if (!tex)
|
||||
continue;
|
||||
|
||||
if (tex->IsFeedback(mWebGL, funcName, texUnit, fbAttachments)) {
|
||||
if (attachList &&
|
||||
tex->IsFeedback(mWebGL, funcName, texUnit, *attachList))
|
||||
{
|
||||
*out_error = true;
|
||||
return;
|
||||
}
|
||||
|
@ -587,7 +589,8 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
|
|||
Draw_cleanup(funcName);
|
||||
}
|
||||
|
||||
void WebGLContext::Draw_cleanup(const char* funcName)
|
||||
void
|
||||
WebGLContext::Draw_cleanup(const char* funcName)
|
||||
{
|
||||
UndoFakeVertexAttrib0();
|
||||
|
||||
|
@ -614,9 +617,12 @@ void WebGLContext::Draw_cleanup(const char* funcName)
|
|||
uint32_t destHeight = mViewportHeight;
|
||||
|
||||
if (mBoundDrawFramebuffer) {
|
||||
const auto& fba = mBoundDrawFramebuffer->ColorAttachment(0);
|
||||
if (fba.IsDefined()) {
|
||||
fba.Size(&destWidth, &destHeight);
|
||||
const auto& drawBuffers = mBoundDrawFramebuffer->ColorDrawBuffers();
|
||||
for (const auto& cur : drawBuffers) {
|
||||
if (!cur->IsDefined())
|
||||
continue;
|
||||
cur->Size(&destWidth, &destHeight);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
destWidth = mWidth;
|
||||
|
|
|
@ -144,76 +144,37 @@ WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
|
|||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
mDefaultFB_DrawBuffer0 = buffers[0];
|
||||
gl->Screen()->SetDrawBuffer(buffers[0]);
|
||||
if (mBoundDrawFramebuffer) {
|
||||
mBoundDrawFramebuffer->DrawBuffers(funcName, buffers);
|
||||
return;
|
||||
}
|
||||
|
||||
// Framebuffer object (not default framebuffer)
|
||||
|
||||
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);
|
||||
// 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;
|
||||
}
|
||||
|
||||
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.
|
||||
switch (buffers[0]) {
|
||||
case LOCAL_GL_NONE:
|
||||
case LOCAL_GL_BACK:
|
||||
break;
|
||||
|
||||
// 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.
|
||||
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;
|
||||
}
|
||||
default:
|
||||
ErrorInvalidOperation("%s: For the default framebuffer, `buffers[0]` must be"
|
||||
" BACK or NONE.",
|
||||
funcName);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
mDefaultFB_DrawBuffer0 = buffers[0];
|
||||
gl->Screen()->SetDrawBuffer(buffers[0]);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -252,10 +252,11 @@ WebGLContext::BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
|
|||
GLenum
|
||||
WebGLContext::CheckFramebufferStatus(GLenum target)
|
||||
{
|
||||
const char funcName[] = "checkFramebufferStatus";
|
||||
if (IsContextLost())
|
||||
return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
|
||||
if (!ValidateFramebufferTarget(target, "invalidateFramebuffer"))
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
return 0;
|
||||
|
||||
WebGLFramebuffer* fb;
|
||||
|
@ -276,8 +277,7 @@ WebGLContext::CheckFramebufferStatus(GLenum target)
|
|||
if (!fb)
|
||||
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
|
||||
|
||||
nsCString fbErrorInfo;
|
||||
return fb->CheckFramebufferStatus(target, &fbErrorInfo).get();
|
||||
return fb->CheckFramebufferStatus(funcName).get();
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLProgram>
|
||||
|
@ -484,10 +484,11 @@ void
|
|||
WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment,
|
||||
GLenum rbtarget, WebGLRenderbuffer* wrb)
|
||||
{
|
||||
const char funcName[] = "framebufferRenderbuffer";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
return;
|
||||
|
||||
WebGLFramebuffer* fb;
|
||||
|
@ -505,20 +506,10 @@ WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment,
|
|||
MOZ_CRASH("GFX: Bad target.");
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify"
|
||||
" framebuffer 0.");
|
||||
}
|
||||
if (!fb)
|
||||
return ErrorInvalidOperation("%s: Cannot modify framebuffer 0.", funcName);
|
||||
|
||||
if (rbtarget != LOCAL_GL_RENDERBUFFER) {
|
||||
return ErrorInvalidEnumInfo("framebufferRenderbuffer: rbtarget:",
|
||||
rbtarget);
|
||||
}
|
||||
|
||||
if (!ValidateFramebufferAttachment(fb, attachment, "framebufferRenderbuffer"))
|
||||
return;
|
||||
|
||||
fb->FramebufferRenderbuffer(attachment, rbtarget, wrb);
|
||||
fb->FramebufferRenderbuffer(funcName, attachment, rbtarget, wrb);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -528,57 +519,13 @@ WebGLContext::FramebufferTexture2D(GLenum target,
|
|||
WebGLTexture* tobj,
|
||||
GLint level)
|
||||
{
|
||||
const char funcName[] = "framebufferTexture2D";
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateFramebufferTarget(target, "framebufferTexture2D"))
|
||||
if (!ValidateFramebufferTarget(target, funcName))
|
||||
return;
|
||||
|
||||
if (level < 0) {
|
||||
ErrorInvalidValue("framebufferTexture2D: level must not be negative.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (textarget != LOCAL_GL_TEXTURE_2D &&
|
||||
(textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
|
||||
textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
|
||||
{
|
||||
return ErrorInvalidEnumInfo("framebufferTexture2D: textarget:",
|
||||
textarget);
|
||||
}
|
||||
|
||||
if (IsWebGL2()) {
|
||||
/* GLES 3.0.4 p208:
|
||||
* If textarget is one of TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||
* TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||
* TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
* or TEXTURE_CUBE_MAP_NEGATIVE_Z, then level must be greater
|
||||
* than or equal to zero and less than or equal to log2 of the
|
||||
* value of MAX_CUBE_MAP_TEXTURE_SIZE. If textarget is TEXTURE_2D,
|
||||
* level must be greater than or equal to zero and no larger than
|
||||
* log2 of the value of MAX_TEXTURE_SIZE. Otherwise, an
|
||||
* INVALID_VALUE error is generated.
|
||||
*/
|
||||
|
||||
if (textarget == LOCAL_GL_TEXTURE_2D) {
|
||||
if (uint32_t(level) > FloorLog2(mImplMaxTextureSize)) {
|
||||
ErrorInvalidValue("framebufferTexture2D: level is too large.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(textarget >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
|
||||
textarget <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
|
||||
|
||||
if (uint32_t(level) > FloorLog2(mImplMaxCubeMapTextureSize)) {
|
||||
ErrorInvalidValue("framebufferTexture2D: level is too large.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (level != 0) {
|
||||
ErrorInvalidValue("framebufferTexture2D: level must be 0.");
|
||||
return;
|
||||
}
|
||||
|
||||
WebGLFramebuffer* fb;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
|
@ -594,15 +541,10 @@ WebGLContext::FramebufferTexture2D(GLenum target,
|
|||
MOZ_CRASH("GFX: Bad target.");
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
return ErrorInvalidOperation("framebufferTexture2D: cannot modify"
|
||||
" framebuffer 0.");
|
||||
}
|
||||
if (!fb)
|
||||
return ErrorInvalidOperation("%s: Cannot modify framebuffer 0.", funcName);
|
||||
|
||||
if (!ValidateFramebufferAttachment(fb, attachment, "framebufferTexture2D"))
|
||||
return;
|
||||
|
||||
fb->FramebufferTexture2D(attachment, textarget, tobj, level);
|
||||
fb->FramebufferTexture2D(funcName, attachment, textarget, tobj, level);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -27,31 +27,34 @@ class WebGLTexture;
|
|||
template<typename T>
|
||||
class PlacementArray;
|
||||
|
||||
class WebGLFBAttachPoint
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
} // namespace gl
|
||||
|
||||
class WebGLFBAttachPoint final
|
||||
{
|
||||
friend class WebGLFramebuffer;
|
||||
public:
|
||||
WebGLFramebuffer* const mFB;
|
||||
const GLenum mAttachmentPoint;
|
||||
private:
|
||||
|
||||
protected:
|
||||
WebGLRefPtr<WebGLTexture> mTexturePtr;
|
||||
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
|
||||
TexImageTarget mTexImageTarget;
|
||||
GLint mTexImageLayer;
|
||||
uint32_t mTexImageLevel;
|
||||
|
||||
// PlacementArray needs a default constructor.
|
||||
template<typename T>
|
||||
friend class PlacementArray;
|
||||
////
|
||||
|
||||
WebGLFBAttachPoint()
|
||||
: mFB(nullptr)
|
||||
, mAttachmentPoint(0)
|
||||
{ }
|
||||
WebGLFBAttachPoint();
|
||||
WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint);
|
||||
|
||||
public:
|
||||
WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint);
|
||||
~WebGLFBAttachPoint();
|
||||
|
||||
////
|
||||
|
||||
void Unlink();
|
||||
|
||||
bool IsDefined() const;
|
||||
|
@ -65,23 +68,13 @@ public:
|
|||
|
||||
void Clear();
|
||||
|
||||
void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level);
|
||||
void SetTexImageLayer(WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
GLint layer);
|
||||
void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
GLint layer = 0);
|
||||
void SetRenderbuffer(WebGLRenderbuffer* rb);
|
||||
|
||||
const WebGLTexture* Texture() const {
|
||||
return mTexturePtr;
|
||||
}
|
||||
WebGLTexture* Texture() {
|
||||
return mTexturePtr;
|
||||
}
|
||||
const WebGLRenderbuffer* Renderbuffer() const {
|
||||
return mRenderbufferPtr;
|
||||
}
|
||||
WebGLRenderbuffer* Renderbuffer() {
|
||||
return mRenderbufferPtr;
|
||||
}
|
||||
WebGLTexture* Texture() const { return mTexturePtr; }
|
||||
WebGLRenderbuffer* Renderbuffer() const { return mRenderbufferPtr; }
|
||||
|
||||
TexImageTarget ImageTarget() const {
|
||||
return mTexImageTarget;
|
||||
}
|
||||
|
@ -94,70 +87,45 @@ public:
|
|||
void AttachmentName(nsCString* out) const;
|
||||
|
||||
bool HasUninitializedImageData() const;
|
||||
void SetImageDataStatus(WebGLImageDataStatus x);
|
||||
void SetImageDataStatus(WebGLImageDataStatus x) const;
|
||||
|
||||
void Size(uint32_t* const out_width, uint32_t* const out_height) const;
|
||||
|
||||
bool HasImage() const;
|
||||
bool IsComplete(WebGLContext* webgl, nsCString* const out_info) const;
|
||||
|
||||
void FinalizeAttachment(gl::GLContext* gl, FBTarget target,
|
||||
GLenum attachmentLoc) const;
|
||||
void Resolve(gl::GLContext* gl, FBTarget target) const;
|
||||
|
||||
JS::Value GetParameter(const char* funcName, WebGLContext* webgl, JSContext* cx,
|
||||
GLenum target, GLenum attachment, GLenum pname,
|
||||
ErrorResult* const out_error);
|
||||
ErrorResult* const out_error) const;
|
||||
|
||||
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))
|
||||
{ }
|
||||
struct Ordered {
|
||||
const WebGLFBAttachPoint& mRef;
|
||||
|
||||
~PlacementArray() {
|
||||
for (auto& cur : *this) {
|
||||
cur.~T();
|
||||
Ordered(const WebGLFBAttachPoint& ref)
|
||||
: mRef(ref)
|
||||
{ }
|
||||
|
||||
bool operator<(const Ordered& other) const {
|
||||
MOZ_ASSERT(mRef.IsDefined() && other.mRef.IsDefined());
|
||||
|
||||
#define ORDER_BY(X) if (X != other.X) return X < other.X;
|
||||
|
||||
ORDER_BY(mRef.mRenderbufferPtr)
|
||||
ORDER_BY(mRef.mTexturePtr)
|
||||
ORDER_BY(mRef.mTexImageTarget.get())
|
||||
ORDER_BY(mRef.mTexImageLevel)
|
||||
ORDER_BY(mRef.mTexImageLayer)
|
||||
|
||||
#undef ORDER_BY
|
||||
return false;
|
||||
}
|
||||
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("GFX: Bad EmplaceAppend.");
|
||||
|
||||
// Placement `new`:
|
||||
new (&(mArray[mSize])) T(a, b);
|
||||
++mSize;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class WebGLFramebuffer final
|
||||
|
@ -174,28 +142,7 @@ public:
|
|||
|
||||
const GLuint mGLName;
|
||||
|
||||
private:
|
||||
mutable bool mIsKnownFBComplete;
|
||||
|
||||
GLenum mReadBufferMode;
|
||||
|
||||
// No need to chase pointers for the oft-used color0.
|
||||
WebGLFBAttachPoint mColorAttachment0;
|
||||
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;
|
||||
}
|
||||
|
||||
protected:
|
||||
#ifdef ANDROID
|
||||
// Bug 1140459: Some drivers (including our test slaves!) don't
|
||||
// give reasonable answers for IsRenderbuffer, maybe others.
|
||||
|
@ -205,94 +152,131 @@ private:
|
|||
bool mIsFB;
|
||||
#endif
|
||||
|
||||
////
|
||||
|
||||
WebGLFBAttachPoint mDepthAttachment;
|
||||
WebGLFBAttachPoint mStencilAttachment;
|
||||
WebGLFBAttachPoint mDepthStencilAttachment;
|
||||
|
||||
// In theory, this number can be unbounded based on the driver. However, no driver
|
||||
// appears to expose more than 8. We might as well stop there too, for now.
|
||||
// (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS)
|
||||
static const size_t kMaxColorAttachments = 8; // jgilbert's MacBook Pro exposes 8.
|
||||
WebGLFBAttachPoint mColorAttachments[kMaxColorAttachments];
|
||||
|
||||
////
|
||||
|
||||
std::vector<const WebGLFBAttachPoint*> mColorDrawBuffers; // Non-null
|
||||
const WebGLFBAttachPoint* mColorReadBuffer; // Null if NONE
|
||||
|
||||
////
|
||||
|
||||
struct ResolvedData {
|
||||
// BlitFramebuffer
|
||||
bool hasSampleBuffers;
|
||||
const WebGLFBAttachPoint* depthBuffer;
|
||||
const WebGLFBAttachPoint* stencilBuffer;
|
||||
|
||||
// IsFeedback
|
||||
std::vector<const WebGLFBAttachPoint*> texDrawBuffers; // Non-null
|
||||
std::set<WebGLFBAttachPoint::Ordered> drawSet;
|
||||
std::set<WebGLFBAttachPoint::Ordered> readSet;
|
||||
|
||||
ResolvedData(const WebGLFramebuffer& parent);
|
||||
};
|
||||
|
||||
UniquePtr<const ResolvedData> mResolvedCompleteData;
|
||||
|
||||
////
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer)
|
||||
|
||||
WebGLFramebuffer(WebGLContext* webgl, GLuint fbo);
|
||||
|
||||
WebGLContext* GetParentObject() const { return mContext; }
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
|
||||
|
||||
private:
|
||||
~WebGLFramebuffer() {
|
||||
DeleteOnce();
|
||||
}
|
||||
|
||||
const WebGLRectangleObject& GetAnyRectObject() const;
|
||||
|
||||
public:
|
||||
void Delete();
|
||||
|
||||
void FramebufferRenderbuffer(GLenum attachment, RBTarget rbtarget,
|
||||
WebGLRenderbuffer* rb);
|
||||
void FramebufferTexture2D(GLenum attachment, TexImageTarget texImageTarget,
|
||||
WebGLTexture* tex, GLint level);
|
||||
void FramebufferTextureLayer(GLenum attachment, WebGLTexture* tex, GLint level,
|
||||
GLint layer);
|
||||
////
|
||||
|
||||
bool HasDefinedAttachments() const;
|
||||
bool HasIncompleteAttachments(nsCString* const out_info) const;
|
||||
bool AllImageRectsMatch() const;
|
||||
bool AllImageSamplesMatch() const;
|
||||
FBStatus PrecheckFramebufferStatus(nsCString* const out_info) const;
|
||||
FBStatus CheckFramebufferStatus(FBTarget target, nsCString* const out_info) const;
|
||||
|
||||
const webgl::FormatUsageInfo*
|
||||
GetFormatForAttachment(const WebGLFBAttachPoint& attachment) const;
|
||||
|
||||
const WebGLFBAttachPoint& ColorAttachment(size_t colorAttachmentId) const {
|
||||
MOZ_ASSERT(colorAttachmentId < 1 + mMoreColorAttachments.Size());
|
||||
return colorAttachmentId ? mMoreColorAttachments[colorAttachmentId - 1]
|
||||
: mColorAttachment0;
|
||||
}
|
||||
|
||||
const WebGLFBAttachPoint& DepthAttachment() const {
|
||||
return mDepthAttachment;
|
||||
}
|
||||
|
||||
const WebGLFBAttachPoint& StencilAttachment() const {
|
||||
return mStencilAttachment;
|
||||
}
|
||||
|
||||
const WebGLFBAttachPoint& DepthStencilAttachment() const {
|
||||
return mDepthStencilAttachment;
|
||||
}
|
||||
|
||||
void SetReadBufferMode(GLenum readBufferMode) {
|
||||
mReadBufferMode = readBufferMode;
|
||||
}
|
||||
|
||||
GLenum ReadBufferMode() const { return mReadBufferMode; }
|
||||
|
||||
void GatherAttachments(std::vector<const WebGLFBAttachPoint*>* const out) const;
|
||||
|
||||
protected:
|
||||
WebGLFBAttachPoint* GetAttachPoint(GLenum attachment); // Fallible
|
||||
Maybe<WebGLFBAttachPoint*> GetAttachPoint(GLenum attachment); // Fallible
|
||||
Maybe<WebGLFBAttachPoint*> GetColorAttachPoint(GLenum attachment); // Fallible
|
||||
void ResolveAttachments(FBTarget target) const;
|
||||
bool ResolveAttachmentData(const char* funcName) const;
|
||||
|
||||
public:
|
||||
void DetachTexture(const WebGLTexture* tex);
|
||||
|
||||
void DetachRenderbuffer(const WebGLRenderbuffer* rb);
|
||||
|
||||
WebGLContext* GetParentObject() const {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
void FinalizeAttachments(FBTarget target) const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer)
|
||||
|
||||
bool ValidateAndInitAttachments(const char* funcName);
|
||||
|
||||
void InvalidateFramebufferStatus() const {
|
||||
mIsKnownFBComplete = false;
|
||||
}
|
||||
|
||||
bool ValidateForRead(const char* info,
|
||||
const webgl::FormatUsageInfo** const out_format,
|
||||
uint32_t* const out_width, uint32_t* const out_height);
|
||||
|
||||
////////////////
|
||||
// Getters
|
||||
|
||||
#define GETTER(X) const decltype(m##X)& X() const { return m##X; }
|
||||
|
||||
GETTER(DepthAttachment)
|
||||
GETTER(StencilAttachment)
|
||||
GETTER(DepthStencilAttachment)
|
||||
GETTER(ColorDrawBuffers)
|
||||
GETTER(ColorReadBuffer)
|
||||
GETTER(ResolvedCompleteData)
|
||||
|
||||
#undef GETTER
|
||||
|
||||
////////////////
|
||||
// Invalidation
|
||||
|
||||
bool IsResolvedComplete() const { return bool(mResolvedCompleteData); }
|
||||
|
||||
void InvalidateFramebufferStatus() {
|
||||
mResolvedCompleteData = nullptr;
|
||||
}
|
||||
|
||||
void RecacheResolvedData();
|
||||
|
||||
////////////////
|
||||
// WebGL funcs
|
||||
|
||||
FBStatus CheckFramebufferStatus(const char* funcName);
|
||||
void FramebufferRenderbuffer(const char* funcName, GLenum attachment, GLenum rbtarget,
|
||||
WebGLRenderbuffer* rb);
|
||||
void FramebufferTexture2D(const char* funcName, GLenum attachment,
|
||||
GLenum texImageTarget, WebGLTexture* tex, GLint level);
|
||||
void FramebufferTextureLayer(const char* funcName, GLenum attachment,
|
||||
WebGLTexture* tex, GLint level, GLint layer);
|
||||
void DrawBuffers(const char* funcName, const dom::Sequence<GLenum>& buffers);
|
||||
void ReadBuffer(const char* funcName, GLenum attachPoint);
|
||||
|
||||
JS::Value GetAttachmentParameter(const char* funcName, JSContext* cx, GLenum target,
|
||||
GLenum attachment, GLenum pname,
|
||||
ErrorResult* const out_error);
|
||||
|
||||
static void BlitFramebuffer(WebGLContext* webgl,
|
||||
const WebGLFramebuffer* src, GLint srcX0, GLint srcY0,
|
||||
GLint srcX1, GLint srcY1,
|
||||
const WebGLFramebuffer* dst, GLint dstX0, GLint dstY0,
|
||||
GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -234,14 +234,14 @@ WebGLRenderbuffer::DoFramebufferRenderbuffer(FBTarget target, GLenum attachment)
|
|||
|
||||
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
const GLuint stencilRB = (mSecondaryRB ? mSecondaryRB : mPrimaryRB);
|
||||
gl->fFramebufferRenderbuffer(target, LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
gl->fFramebufferRenderbuffer(target.get(), LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER, mPrimaryRB);
|
||||
gl->fFramebufferRenderbuffer(target, LOCAL_GL_STENCIL_ATTACHMENT,
|
||||
gl->fFramebufferRenderbuffer(target.get(), LOCAL_GL_STENCIL_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER, stencilRB);
|
||||
return;
|
||||
}
|
||||
|
||||
gl->fFramebufferRenderbuffer(target, attachment,
|
||||
gl->fFramebufferRenderbuffer(target.get(), attachment,
|
||||
LOCAL_GL_RENDERBUFFER, mPrimaryRB);
|
||||
}
|
||||
|
||||
|
|
|
@ -1969,20 +1969,18 @@ WebGLTexture::ValidateCopyTexImageForFeedback(const char* funcName, uint32_t lev
|
|||
{
|
||||
const auto& fb = mContext->mBoundReadFramebuffer;
|
||||
if (fb) {
|
||||
const auto readBuffer = fb->ReadBufferMode();
|
||||
MOZ_ASSERT(readBuffer != LOCAL_GL_NONE);
|
||||
const uint32_t colorAttachment = readBuffer - LOCAL_GL_COLOR_ATTACHMENT0;
|
||||
const auto& attach = fb->ColorAttachment(colorAttachment);
|
||||
const auto& attach = fb->ColorReadBuffer();
|
||||
MOZ_ASSERT(attach);
|
||||
|
||||
if (attach.Texture() == this &&
|
||||
uint32_t(attach.MipLevel()) == level)
|
||||
if (attach->Texture() == this &&
|
||||
uint32_t(attach->MipLevel()) == level)
|
||||
{
|
||||
// Note that the TexImageTargets *don't* have to match for this to be
|
||||
// undefined per GLES 3.0.4 p211, thus an INVALID_OP in WebGL.
|
||||
mContext->ErrorInvalidOperation("%s: Feedback loop detected, as this texture"
|
||||
" is already attached to READ_FRAMEBUFFER's"
|
||||
" READ_BUFFER-selected COLOR_ATTACHMENT%u.",
|
||||
funcName, colorAttachment);
|
||||
funcName, attach->mAttachmentPoint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче