#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 glw { class Functions; class FunctionLoader; } 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((deUint32)a|(deUint32)b); } inline ContextFlags operator& (ContextFlags a, ContextFlags b) { return ContextFlags((deUint32)a&(deUint32)b); } inline ContextFlags operator~ (ContextFlags a) { return ContextFlags(~(deUint32)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; } deUint32 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 (deUint32 bits) : m_bits(bits) {} static ApiType fromBits (deUint32 bits) { return ApiType(bits); } static deUint32 pack (int major, int minor, Profile profile); deUint32 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 deUint32 ApiType::pack (int major, int minor, Profile profile) { deUint32 bits = 0; DE_ASSERT((deUint32(major) & ~((1<<MAJOR_BITS)-1)) == 0); DE_ASSERT((deUint32(minor) & ~((1<<MINOR_BITS)-1)) == 0); DE_ASSERT((deUint32(profile) & ~((1<<PROFILE_BITS)-1)) == 0); bits |= deUint32(major) << MAJOR_SHIFT; bits |= deUint32(minor) << MINOR_SHIFT; bits |= deUint32(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)); } 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 deUint32 pack (deUint32 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 deUint32 ContextType::pack (deUint32 apiBits, ContextFlags flags) { deUint32 bits = apiBits; DE_ASSERT((deUint32(flags) & ~((1u<<FLAGS_BITS)-1u)) == 0); bits |= deUint32(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; } 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 deUint32 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); 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); } // glu #endif // _GLURENDERCONTEXT_HPP