GLenum FramebufferGL::getImplementationColorReadType() const { const FramebufferAttachment *readAttachment = mState.getReadAttachment(); GLenum internalFormat = readAttachment->getInternalFormat(); const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat); return internalFormatInfo.type; }
ClearParameters State::getClearParameters(GLbitfield mask) const { ClearParameters clearParams; memset(&clearParams, 0, sizeof(ClearParameters)); for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { clearParams.clearColor[i] = false; } clearParams.colorFClearValue = mColorClearValue; clearParams.colorClearType = GL_FLOAT; clearParams.colorMaskRed = mBlend.colorMaskRed; clearParams.colorMaskGreen = mBlend.colorMaskGreen; clearParams.colorMaskBlue = mBlend.colorMaskBlue; clearParams.colorMaskAlpha = mBlend.colorMaskAlpha; clearParams.clearDepth = false; clearParams.depthClearValue = mDepthClearValue; clearParams.clearStencil = false; clearParams.stencilClearValue = mStencilClearValue; clearParams.stencilWriteMask = mDepthStencil.stencilWritemask; clearParams.scissorEnabled = mScissorTest; clearParams.scissor = mScissor; const Framebuffer *framebufferObject = getDrawFramebuffer(); if (mask & GL_COLOR_BUFFER_BIT) { if (framebufferObject->hasEnabledColorAttachment()) { for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { clearParams.clearColor[i] = true; } } } if (mask & GL_DEPTH_BUFFER_BIT) { if (mDepthStencil.depthMask && framebufferObject->getDepthbuffer() != NULL) { clearParams.clearDepth = true; } } if (mask & GL_STENCIL_BUFFER_BIT) { if (framebufferObject->getStencilbuffer() != NULL) { GLenum stencilActualFormat = framebufferObject->getStencilbuffer()->getActualFormat(); if (GetInternalFormatInfo(stencilActualFormat).stencilBits > 0) { clearParams.clearStencil = true; } } } return clearParams; }
void Framebuffer::setAttachment(GLenum type, GLenum binding, const ImageIndex &textureIndex, FramebufferAttachmentObject *resource) { if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT) { // ensure this is a legitimate depth+stencil format FramebufferAttachmentObject *attachmentObj = resource; if (resource) { FramebufferAttachment::Target target(binding, textureIndex); GLenum internalFormat = resource->getAttachmentInternalFormat(target); const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat); if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0) { // Attaching nullptr detaches the current attachment. attachmentObj = nullptr; } } mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj); mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj); mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT); mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT); } else { switch (binding) { case GL_DEPTH: case GL_DEPTH_ATTACHMENT: mState.mDepthAttachment.attach(type, binding, textureIndex, resource); mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT); break; case GL_STENCIL: case GL_STENCIL_ATTACHMENT: mState.mStencilAttachment.attach(type, binding, textureIndex, resource); mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT); break; case GL_BACK: mState.mColorAttachments[0].attach(type, binding, textureIndex, resource); mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0); break; default: { size_t colorIndex = binding - GL_COLOR_ATTACHMENT0; ASSERT(colorIndex < mState.mColorAttachments.size()); mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource); mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex); } break; } } }
void Context::initCaps(GLuint clientVersion) { mCaps = mRenderer->getRendererCaps(); mExtensions = mRenderer->getRendererExtensions(); if (clientVersion < 3) { // Disable ES3+ extensions mExtensions.colorBufferFloat = false; } if (clientVersion > 2) { // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts //mExtensions.sRGB = false; } // Apply implementation limits mCaps.maxVertexAttributes = std::min<GLuint>(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS); mCaps.maxVertexUniformBlocks = std::min<GLuint>(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS); mCaps.maxVertexOutputComponents = std::min<GLuint>(mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); mCaps.compressedTextureFormats.clear(); const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++) { GLenum format = i->first; TextureCaps formatCaps = i->second; const InternalFormat &formatInfo = GetInternalFormatInfo(format); // Update the format caps based on the client version and extensions formatCaps.texturable = formatInfo.textureSupport(clientVersion, mExtensions); formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions); formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions); // OpenGL ES does not support multisampling with integer formats if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT) { formatCaps.sampleCounts.clear(); } if (formatCaps.texturable && formatInfo.compressed) { mCaps.compressedTextureFormats.push_back(format); } mTextureCaps.insert(format, formatCaps); } }
GLenum FramebufferAttachment::getColorEncoding() const { return GetInternalFormatInfo(getInternalFormat()).colorEncoding; }
GLuint FramebufferAttachment::getStencilSize() const { return GetInternalFormatInfo(getInternalFormat()).stencilBits; }
GLenum FramebufferAttachment::getComponentType() const { return GetInternalFormatInfo(getInternalFormat()).componentType; }
GLuint FramebufferAttachment::getAlphaSize() const { return GetInternalFormatInfo(getInternalFormat()).alphaBits; }
GLuint FramebufferAttachment::getDepthSize() const { return GetInternalFormatInfo(getInternalFormat()).depthBits; }
GLuint Renderbuffer::getAlphaSize() const { return GetInternalFormatInfo(getActualFormat()).alphaBits; }
GLuint FramebufferAttachment::getGreenSize() const { return (GetInternalFormatInfo(getInternalFormat()).greenBits > 0) ? GetInternalFormatInfo(getActualFormat()).greenBits : 0; }
GLuint Renderbuffer::getStencilSize() const { return GetInternalFormatInfo(getActualFormat()).stencilBits; }
GLuint Renderbuffer::getGreenSize() const { return GetInternalFormatInfo(getActualFormat()).greenBits; }
GLenum Framebuffer::checkStatus(const ContextState &data) const { // The default framebuffer *must* always be complete, though it may not be // subject to the same rules as application FBOs. ie, it could have 0x0 size. if (mId == 0) { return GL_FRAMEBUFFER_COMPLETE; } unsigned int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments) { if (colorAttachment.isAttached()) { const Extents &size = colorAttachment.getSize(); if (size.width == 0 || size.height == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = colorAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (colorAttachment.type() == GL_TEXTURE) { if (!formatCaps.renderable) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (colorAttachment.layer() >= size.depth) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } // ES3 specifies that cube map texture attachments must be cube complete. // This language is missing from the ES2 spec, but we enforce it here because some // desktop OpenGL drivers also enforce this validation. // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness. const Texture *texture = colorAttachment.getTexture(); ASSERT(texture); if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete()) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else if (colorAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (!missingAttachment) { // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that // all color attachments have the same number of samples for the FBO to be complete. if (colorAttachment.getSamples() != samples) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; } // in GLES 2.0, all color attachments attachments must have the same number of bitplanes // in GLES 3.0, there is no such restriction if (data.clientVersion < 3) { if (formatInfo.pixelBytes != colorbufferSize) { return GL_FRAMEBUFFER_UNSUPPORTED; } } } else { samples = colorAttachment.getSamples(); colorbufferSize = formatInfo.pixelBytes; missingAttachment = false; } } } const FramebufferAttachment &depthAttachment = mState.mDepthAttachment; if (depthAttachment.isAttached()) { const Extents &size = depthAttachment.getSize(); if (size.width == 0 || size.height == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = depthAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (depthAttachment.type() == GL_TEXTURE) { // depth texture attachments require OES/ANGLE_depth_texture if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (!formatCaps.renderable) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else if (depthAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (missingAttachment) { samples = depthAttachment.getSamples(); missingAttachment = false; } else if (samples != depthAttachment.getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment; if (stencilAttachment.isAttached()) { const Extents &size = stencilAttachment.getSize(); if (size.width == 0 || size.height == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = stencilAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (stencilAttachment.type() == GL_TEXTURE) { // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (!formatCaps.renderable) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else if (stencilAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (missingAttachment) { samples = stencilAttachment.getSamples(); missingAttachment = false; } else if (samples != stencilAttachment.getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } // Starting from ES 3.0 stencil and depth, if present, should be the same image if (data.clientVersion >= 3 && depthAttachment.isAttached() && stencilAttachment != depthAttachment) { return GL_FRAMEBUFFER_UNSUPPORTED; } } // we need to have at least one attachment to be complete if (missingAttachment) { return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; } // In ES 2.0, all color attachments must have the same width and height. // In ES 3.0, there is no such restriction. if (data.clientVersion < 3 && !mState.attachmentsHaveSameDimensions()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } syncState(); if (!mImpl->checkStatus()) { return GL_FRAMEBUFFER_UNSUPPORTED; } return GL_FRAMEBUFFER_COMPLETE; }
GLenum Framebuffer::completeness(const gl::Data &data) const { int width = 0; int height = 0; unsigned int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment]; if (colorbuffer) { if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = colorbuffer->getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (colorbuffer->isTexture()) { if (!formatCaps.renderable) { return GL_FRAMEBUFFER_UNSUPPORTED; } if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (!missingAttachment) { // all color attachments must have the same width and height if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that // all color attachments have the same number of samples for the FBO to be complete. if (colorbuffer->getSamples() != samples) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; } // in GLES 2.0, all color attachments attachments must have the same number of bitplanes // in GLES 3.0, there is no such restriction if (data.clientVersion < 3) { if (formatInfo.pixelBytes != colorbufferSize) { return GL_FRAMEBUFFER_UNSUPPORTED; } } // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) { const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment]; if (previousAttachment && (colorbuffer->id() == previousAttachment->id() && colorbuffer->type() == previousAttachment->type())) { return GL_FRAMEBUFFER_UNSUPPORTED; } } } else { width = colorbuffer->getWidth(); height = colorbuffer->getHeight(); samples = colorbuffer->getSamples(); colorbufferSize = formatInfo.pixelBytes; missingAttachment = false; } } } if (mDepthbuffer) { if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = mDepthbuffer->getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mDepthbuffer->isTexture()) { // depth texture attachments require OES/ANGLE_depth_texture if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (!formatCaps.renderable) { return GL_FRAMEBUFFER_UNSUPPORTED; } if (formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { if (!formatCaps.renderable || formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (missingAttachment) { width = mDepthbuffer->getWidth(); height = mDepthbuffer->getHeight(); samples = mDepthbuffer->getSamples(); missingAttachment = false; } else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } else if (samples != mDepthbuffer->getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } if (mStencilbuffer) { if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = mStencilbuffer->getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mStencilbuffer->isTexture()) { // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (!formatCaps.renderable) { return GL_FRAMEBUFFER_UNSUPPORTED; } if (formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { if (!formatCaps.renderable || formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (missingAttachment) { width = mStencilbuffer->getWidth(); height = mStencilbuffer->getHeight(); samples = mStencilbuffer->getSamples(); missingAttachment = false; } else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } else if (samples != mStencilbuffer->getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } // if we have both a depth and stencil buffer, they must refer to the same object // since we only support packed_depth_stencil and not separate depth and stencil if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil()) { return GL_FRAMEBUFFER_UNSUPPORTED; } // we need to have at least one attachment to be complete if (missingAttachment) { return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; } return GL_FRAMEBUFFER_COMPLETE; }
GLenum Framebuffer::checkStatus(const gl::Data &data) const { // The default framebuffer *must* always be complete, though it may not be // subject to the same rules as application FBOs. ie, it could have 0x0 size. if (mId == 0) { return GL_FRAMEBUFFER_COMPLETE; } int width = 0; int height = 0; unsigned int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments) { if (colorAttachment.isAttached()) { if (colorAttachment.getWidth() == 0 || colorAttachment.getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = colorAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (colorAttachment.type() == GL_TEXTURE) { if (!formatCaps.renderable) { return GL_FRAMEBUFFER_UNSUPPORTED; } if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else if (colorAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (!missingAttachment) { // all color attachments must have the same width and height if (colorAttachment.getWidth() != width || colorAttachment.getHeight() != height) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that // all color attachments have the same number of samples for the FBO to be complete. if (colorAttachment.getSamples() != samples) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; } // in GLES 2.0, all color attachments attachments must have the same number of bitplanes // in GLES 3.0, there is no such restriction if (data.clientVersion < 3) { if (formatInfo.pixelBytes != colorbufferSize) { return GL_FRAMEBUFFER_UNSUPPORTED; } } } else { width = colorAttachment.getWidth(); height = colorAttachment.getHeight(); samples = colorAttachment.getSamples(); colorbufferSize = formatInfo.pixelBytes; missingAttachment = false; } } } const FramebufferAttachment &depthAttachment = mData.mDepthAttachment; if (depthAttachment.isAttached()) { if (depthAttachment.getWidth() == 0 || depthAttachment.getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = depthAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (depthAttachment.type() == GL_TEXTURE) { // depth texture attachments require OES/ANGLE_depth_texture if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (!formatCaps.renderable) { return GL_FRAMEBUFFER_UNSUPPORTED; } if (formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else if (depthAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (missingAttachment) { width = depthAttachment.getWidth(); height = depthAttachment.getHeight(); samples = depthAttachment.getSamples(); missingAttachment = false; } else if (width != depthAttachment.getWidth() || height != depthAttachment.getHeight()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } else if (samples != depthAttachment.getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } const FramebufferAttachment &stencilAttachment = mData.mStencilAttachment; if (stencilAttachment.isAttached()) { if (stencilAttachment.getWidth() == 0 || stencilAttachment.getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } GLenum internalformat = stencilAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (stencilAttachment.type() == GL_TEXTURE) { // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (!formatCaps.renderable) { return GL_FRAMEBUFFER_UNSUPPORTED; } if (formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else if (stencilAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } if (missingAttachment) { width = stencilAttachment.getWidth(); height = stencilAttachment.getHeight(); samples = stencilAttachment.getSamples(); missingAttachment = false; } else if (width != stencilAttachment.getWidth() || height != stencilAttachment.getHeight()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } else if (samples != stencilAttachment.getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } // we need to have at least one attachment to be complete if (missingAttachment) { return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; } return mImpl->checkStatus(); }
GLuint FramebufferAttachment::getDepthSize() const { return (GetInternalFormatInfo(getInternalFormat()).depthBits > 0) ? GetInternalFormatInfo(getActualFormat()).depthBits : 0; }
GLuint FramebufferAttachment::getStencilSize() const { return (GetInternalFormatInfo(getInternalFormat()).stencilBits > 0) ? GetInternalFormatInfo(getActualFormat()).stencilBits : 0; }
GLuint Renderbuffer::getRedSize() const { return GetInternalFormatInfo(getActualFormat()).redBits; }
GLuint FramebufferAttachment::getRedSize() const { return GetInternalFormatInfo(getInternalFormat()).redBits; }
GLuint Renderbuffer::getBlueSize() const { return GetInternalFormatInfo(getActualFormat()).blueBits; }
GLuint FramebufferAttachment::getGreenSize() const { return GetInternalFormatInfo(getInternalFormat()).greenBits; }
GLuint Renderbuffer::getDepthSize() const { return GetInternalFormatInfo(getActualFormat()).depthBits; }
GLuint FramebufferAttachment::getBlueSize() const { return GetInternalFormatInfo(getInternalFormat()).blueBits; }