void test_state() { State* st = new ConcreteStateA; ContextState* con = new ContextState(st); con->OperationChangeState(); con->OperationChangeState(); con->OperationChangeState(); con->OperationChangeState(); con->OperationChangeState(); delete st; delete con; }
Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state) : mImplementation(implFactory->createCompiler()), mSpec(SelectShaderSpec(state.getClientMajorVersion(), state.getClientMinorVersion())), mOutputType(mImplementation->getTranslatorOutputType()), mResources(), mFragmentCompiler(nullptr), mVertexCompiler(nullptr) { ASSERT(state.getClientMajorVersion() == 2 || state.getClientMajorVersion() == 3); const gl::Caps &caps = state.getCaps(); const gl::Extensions &extensions = state.getExtensions(); ShInitBuiltInResources(&mResources); mResources.MaxVertexAttribs = caps.maxVertexAttributes; mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; mResources.MaxVaryingVectors = caps.maxVaryingVectors; mResources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; mResources.MaxTextureImageUnits = caps.maxTextureImageUnits; mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; mResources.MaxDrawBuffers = caps.maxDrawBuffers; mResources.OES_standard_derivatives = extensions.standardDerivatives; mResources.EXT_draw_buffers = extensions.drawBuffers; mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD; mResources.OES_EGL_image_external = extensions.eglImageExternal; mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3; mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal; // TODO: use shader precision caps to determine if high precision is supported? mResources.FragmentPrecisionHigh = 1; mResources.EXT_frag_depth = extensions.fragDepth; // GLSL ES 3.0 constants mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; mResources.MinProgramTexelOffset = caps.minProgramTexelOffset; mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; }
GLenum Framebuffer::checkStatusImpl(const ContextState &state) { ASSERT(mId != 0); 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 = state.getTextureCap(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->getTextureState().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 (state.getClientVersion() < 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 = state.getTextureCap(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (depthAttachment.type() == GL_TEXTURE) { // depth texture attachments require OES/ANGLE_depth_texture if (!state.getExtensions().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()) { // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be // considered complete when its depth or stencil samples are a // multiple of the number of color samples. const bool mixedSamples = state.getExtensions().framebufferMixedSamples; if (!mixedSamples) return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; const int colorSamples = samples ? samples : 1; const int depthSamples = depthAttachment.getSamples(); if ((depthSamples % colorSamples) != 0) 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 = state.getTextureCap(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 (!state.getExtensions().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()) { // see the comments in depth attachment check. const bool mixedSamples = state.getExtensions().framebufferMixedSamples; if (!mixedSamples) return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; const int colorSamples = samples ? samples : 1; const int stencilSamples = stencilAttachment.getSamples(); if ((stencilSamples % colorSamples) != 0) return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } // Starting from ES 3.0 stencil and depth, if present, should be the same image if (state.getClientVersion() >= 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 (state.getClientVersion() < 3 && !mState.attachmentsHaveSameDimensions()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } syncState(); if (!mImpl->checkStatus()) { return GL_FRAMEBUFFER_UNSUPPORTED; } return GL_FRAMEBUFFER_COMPLETE; }