#ifndef _GLURENDERCONTEXT_HPP #define _GLURENDERCONTEXT_HPP /*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES Utilities * ------------------------------------------------ * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief OpenGL ES rendering context. *//*--------------------------------------------------------------------*/ #include "tcuDefs.hpp" // glw::GenericFuncType #include "glwFunctionLoader.hpp" namespace tcu { class CommandLine; class Platform; class RenderTarget; } // namespace tcu namespace glw { class Functions; class FunctionLoader; } // namespace glw namespace glu { class ContextType; class ContextInfo; struct RenderConfig; enum Profile { PROFILE_ES = 0, //!< OpenGL ES PROFILE_CORE, //!< OpenGL Core Profile PROFILE_COMPATIBILITY, //!< OpenGL Compatibility Profile PROFILE_LAST }; enum ContextFlags { CONTEXT_ROBUST = (1 << 0), //!< Robust context CONTEXT_DEBUG = (1 << 1), //!< Debug context CONTEXT_FORWARD_COMPATIBLE = (1 << 2), //!< Forward-compatible context CONTEXT_NO_ERROR = (1 << 3) //!< No error context }; inline ContextFlags operator|(ContextFlags a, ContextFlags b) { return ContextFlags((uint32_t)a | (uint32_t)b); } inline ContextFlags operator&(ContextFlags a, ContextFlags b) { return ContextFlags((uint32_t)a & (uint32_t)b); } inline ContextFlags operator~(ContextFlags a) { return ContextFlags(~(uint32_t)a); } /*--------------------------------------------------------------------*//*! * \brief Rendering API version and profile. *//*--------------------------------------------------------------------*/ class ApiType { public: ApiType(void) : m_bits(pack(0, 0, PROFILE_LAST)) { } ApiType(int major, int minor, Profile profile) : m_bits(pack(major, minor, profile)) { } int getMajorVersion(void) const { return int((m_bits >> MAJOR_SHIFT) & ((1u << MAJOR_BITS) - 1u)); } int getMinorVersion(void) const { return int((m_bits >> MINOR_SHIFT) & ((1u << MINOR_BITS) - 1u)); } Profile getProfile(void) const { return Profile((m_bits >> PROFILE_SHIFT) & ((1u << PROFILE_BITS) - 1u)); } bool operator==(ApiType other) const { return m_bits == other.m_bits; } bool operator!=(ApiType other) const { return m_bits != other.m_bits; } uint32_t getPacked(void) const { return m_bits; } // Shorthands static ApiType es(int major, int minor) { return ApiType(major, minor, PROFILE_ES); } static ApiType core(int major, int minor) { return ApiType(major, minor, PROFILE_CORE); } static ApiType compatibility(int major, int minor) { return ApiType(major, minor, PROFILE_COMPATIBILITY); } protected: ApiType(uint32_t bits) : m_bits(bits) { } static ApiType fromBits(uint32_t bits) { return ApiType(bits); } static uint32_t pack(int major, int minor, Profile profile); uint32_t m_bits; enum { MAJOR_BITS = 4, MINOR_BITS = 4, PROFILE_BITS = 2, TOTAL_API_BITS = MAJOR_BITS + MINOR_BITS + PROFILE_BITS, MAJOR_SHIFT = 0, MINOR_SHIFT = MAJOR_SHIFT + MAJOR_BITS, PROFILE_SHIFT = MINOR_SHIFT + MINOR_BITS }; } DE_WARN_UNUSED_TYPE; inline uint32_t ApiType::pack(int major, int minor, Profile profile) { uint32_t bits = 0; DE_ASSERT((uint32_t(major) & ~((1 << MAJOR_BITS) - 1)) == 0); DE_ASSERT((uint32_t(minor) & ~((1 << MINOR_BITS) - 1)) == 0); DE_ASSERT((uint32_t(profile) & ~((1 << PROFILE_BITS) - 1)) == 0); bits |= uint32_t(major) << MAJOR_SHIFT; bits |= uint32_t(minor) << MINOR_SHIFT; bits |= uint32_t(profile) << PROFILE_SHIFT; return bits; } /*--------------------------------------------------------------------*//*! * \brief Rendering context type. * * ContextType differs from API type by adding context flags. They are * crucial in for example determining when GL core context supports * certain API version (forward-compatible bit). * * \note You should NEVER compare ContextTypes against each other, as * you most likely don't want to take flags into account. For example * the test code almost certainly doesn't want to check that you have * EXACTLY ES3.1 context with debug, but without for example robustness. *//*--------------------------------------------------------------------*/ class ContextType : private ApiType { public: ContextType(void) { } ContextType(int major, int minor, Profile profile, ContextFlags flags = ContextFlags(0)); explicit ContextType(ApiType apiType, ContextFlags flags = ContextFlags(0)); ApiType getAPI(void) const { return ApiType::fromBits(m_bits & ((1u << TOTAL_API_BITS) - 1u)); } void setAPI(const ApiType &apiType) { m_bits = apiType.getPacked(); } ContextFlags getFlags(void) const { return ContextFlags((m_bits >> FLAGS_SHIFT) & ((1u << FLAGS_BITS) - 1u)); } using ApiType::getMajorVersion; using ApiType::getMinorVersion; using ApiType::getProfile; protected: static uint32_t pack(uint32_t apiBits, ContextFlags flags); enum { FLAGS_BITS = 4, TOTAL_CONTEXT_BITS = TOTAL_API_BITS + FLAGS_BITS, FLAGS_SHIFT = TOTAL_API_BITS }; } DE_WARN_UNUSED_TYPE; inline ContextType::ContextType(int major, int minor, Profile profile, ContextFlags flags) : ApiType(major, minor, profile) { m_bits = pack(m_bits, flags); } inline ContextType::ContextType(ApiType apiType, ContextFlags flags) : ApiType(apiType) { m_bits = pack(m_bits, flags); } inline uint32_t ContextType::pack(uint32_t apiBits, ContextFlags flags) { uint32_t bits = apiBits; DE_ASSERT((uint32_t(flags) & ~((1u << FLAGS_BITS) - 1u)) == 0); bits |= uint32_t(flags) << FLAGS_SHIFT; return bits; } inline bool isContextTypeES(ContextType type) { return type.getAPI().getProfile() == PROFILE_ES; } inline bool isContextTypeGLCore(ContextType type) { return type.getAPI().getProfile() == PROFILE_CORE; } inline bool isContextTypeGLCompatibility(ContextType type) { return type.getAPI().getProfile() == PROFILE_COMPATIBILITY; } inline bool isES2Context(ContextType type) { return isContextTypeES(type) && type.getMajorVersion() == 2; } bool contextSupports(ContextType ctxType, ApiType requiredApiType); const char *getApiTypeDescription(ApiType type); /*--------------------------------------------------------------------*//*! * \brief Rendering context abstraction. *//*--------------------------------------------------------------------*/ class RenderContext { public: RenderContext(void) { } virtual ~RenderContext(void) { } //! Get context type. Must match to type given to ContextFactory::createContext(). virtual ContextType getType(void) const = DE_NULL; //! Get GL function table. Should be filled with all core entry points for context type. virtual const glw::Functions &getFunctions(void) const = DE_NULL; //! Get render target information. virtual const tcu::RenderTarget &getRenderTarget(void) const = DE_NULL; //! Do post-render actions (swap buffers for example). virtual void postIterate(void) = DE_NULL; //! Get default framebuffer. virtual uint32_t getDefaultFramebuffer(void) const { return 0; } //! Get extension function address. virtual glw::GenericFuncType getProcAddress(const char *name) const; //! Make context current in thread. Optional to support. virtual void makeCurrent(void); private: RenderContext(const RenderContext &other); // Not allowed! RenderContext &operator=(const RenderContext &other); // Not allowed! }; // Utilities RenderContext *createRenderContext(tcu::Platform &platform, const tcu::CommandLine &cmdLine, const RenderConfig &config, const RenderContext *sharedContext = DE_NULL); RenderContext *createDefaultRenderContext(tcu::Platform &platform, const tcu::CommandLine &cmdLine, ApiType apiType); void initCoreFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType); void initExtensionFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType, int numExtensions, const char *const *extensions); // \note initFunctions() and initExtensionFunctions() without explicit extension list // use glGetString* to query list of extensions, so it needs current GL context. void initFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType); void initExtensionFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType); bool hasExtension(const glw::Functions &gl, ApiType apiType, const std::string &extension); } // namespace glu #endif // _GLURENDERCONTEXT_HPP