1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Display.h: Defines the egl::Display class, representing the abstract 8 // display on which graphics are drawn. Implements EGLDisplay. 9 // [EGL 1.4] section 2.1.2 page 3. 10 11 #ifndef LIBANGLE_DISPLAY_H_ 12 #define LIBANGLE_DISPLAY_H_ 13 14 #include <mutex> 15 #include <vector> 16 17 #include "common/SimpleMutex.h" 18 #include "common/WorkerThread.h" 19 #include "common/platform.h" 20 #include "libANGLE/AttributeMap.h" 21 #include "libANGLE/BlobCache.h" 22 #include "libANGLE/Caps.h" 23 #include "libANGLE/Config.h" 24 #include "libANGLE/Context.h" 25 #include "libANGLE/Debug.h" 26 #include "libANGLE/Error.h" 27 #include "libANGLE/LoggingAnnotator.h" 28 #include "libANGLE/MemoryProgramCache.h" 29 #include "libANGLE/MemoryShaderCache.h" 30 #include "libANGLE/Observer.h" 31 #include "libANGLE/ShareGroup.h" 32 #include "libANGLE/Version.h" 33 #include "platform/Feature.h" 34 #include "platform/autogen/FrontendFeatures_autogen.h" 35 36 // Only DisplayCGL needs to be notified about an EGL call about to be made to prepare 37 // per-thread data. Disable Display::prepareForCall on other platforms for performance. 38 #if !defined(ANGLE_USE_DISPLAY_PREPARE_FOR_CALL) 39 # if ANGLE_ENABLE_CGL 40 # define ANGLE_USE_DISPLAY_PREPARE_FOR_CALL 1 41 # else 42 # define ANGLE_USE_DISPLAY_PREPARE_FOR_CALL 0 43 # endif 44 #endif 45 46 namespace angle 47 { 48 class FrameCaptureShared; 49 } // namespace angle 50 51 namespace gl 52 { 53 class Context; 54 class TextureManager; 55 class SemaphoreManager; 56 } // namespace gl 57 58 namespace rx 59 { 60 class DisplayImpl; 61 class EGLImplFactory; 62 } // namespace rx 63 64 namespace egl 65 { 66 class Device; 67 class Image; 68 class Stream; 69 class Surface; 70 class Sync; 71 class Thread; 72 73 using SurfaceMap = angle::HashMap<GLuint, Surface *>; 74 using ThreadSet = angle::HashSet<Thread *>; 75 76 struct DisplayState final : private angle::NonCopyable 77 { 78 DisplayState(EGLNativeDisplayType nativeDisplayId); 79 ~DisplayState(); 80 81 void notifyDeviceLost() const; 82 83 EGLLabelKHR label; 84 ContextMap contextMap; 85 mutable angle::SimpleMutex contextMapMutex; 86 SurfaceMap surfaceMap; 87 angle::FeatureOverrides featureOverrides; 88 EGLNativeDisplayType displayId; 89 90 // Single-threaded and multithread pools for use by various parts of ANGLE, such as shader 91 // compilation. These pools are internally synchronized. 92 std::shared_ptr<angle::WorkerThreadPool> singleThreadPool; 93 std::shared_ptr<angle::WorkerThreadPool> multiThreadPool; 94 95 mutable bool deviceLost; 96 }; 97 98 // Constant coded here as a reasonable limit. 99 constexpr EGLAttrib kProgramCacheSizeAbsoluteMax = 0x4000000; 100 101 using ImageMap = angle::HashMap<GLuint, Image *>; 102 using StreamSet = angle::HashSet<Stream *>; 103 using SyncMap = angle::HashMap<GLuint, std::unique_ptr<Sync>>; 104 105 class Display final : public LabeledObject, 106 public angle::ObserverInterface, 107 public angle::NonCopyable 108 { 109 public: 110 ~Display() override; 111 112 void setLabel(EGLLabelKHR label) override; 113 EGLLabelKHR getLabel() const override; 114 115 // Observer implementation. 116 void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; 117 118 Error initialize(); 119 120 enum class TerminateReason 121 { 122 Api, 123 InternalCleanup, 124 125 InvalidEnum, 126 EnumCount = InvalidEnum, 127 }; 128 Error terminate(Thread *thread, TerminateReason terminateReason); 129 130 #if ANGLE_USE_DISPLAY_PREPARE_FOR_CALL 131 // Called before all display state dependent EGL functions. Backends can set up, for example, 132 // thread-specific backend state through this function. Not called for functions that do not 133 // need the state. 134 Error prepareForCall(); 135 #endif 136 137 // Called on eglReleaseThread. Backends can tear down thread-specific backend state through 138 // this function. 139 Error releaseThread(); 140 141 static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap); 142 static Display *GetDisplayFromNativeDisplay(EGLenum platform, 143 EGLNativeDisplayType nativeDisplay, 144 const AttributeMap &attribMap); 145 static Display *GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay); 146 147 using EglDisplaySet = angle::HashSet<Display *>; 148 149 static const ClientExtensions &GetClientExtensions(); 150 static const std::string &GetClientExtensionString(); 151 152 std::vector<const Config *> getConfigs(const AttributeMap &attribs) const; 153 std::vector<const Config *> chooseConfig(const AttributeMap &attribs) const; 154 155 Error createWindowSurface(const Config *configuration, 156 EGLNativeWindowType window, 157 const AttributeMap &attribs, 158 Surface **outSurface); 159 Error createPbufferSurface(const Config *configuration, 160 const AttributeMap &attribs, 161 Surface **outSurface); 162 Error createPbufferFromClientBuffer(const Config *configuration, 163 EGLenum buftype, 164 EGLClientBuffer clientBuffer, 165 const AttributeMap &attribs, 166 Surface **outSurface); 167 Error createPixmapSurface(const Config *configuration, 168 NativePixmapType nativePixmap, 169 const AttributeMap &attribs, 170 Surface **outSurface); 171 172 Error createImage(const gl::Context *context, 173 EGLenum target, 174 EGLClientBuffer buffer, 175 const AttributeMap &attribs, 176 Image **outImage); 177 178 Error createStream(const AttributeMap &attribs, Stream **outStream); 179 180 Error createContext(const Config *configuration, 181 gl::Context *shareContext, 182 const AttributeMap &attribs, 183 gl::Context **outContext); 184 185 Error createSync(const gl::Context *currentContext, 186 EGLenum type, 187 const AttributeMap &attribs, 188 Sync **outSync); 189 190 Error makeCurrent(Thread *thread, 191 gl::Context *previousContext, 192 Surface *drawSurface, 193 Surface *readSurface, 194 gl::Context *context); 195 196 Error destroySurface(Surface *surface); 197 void destroyImage(Image *image); 198 void destroyStream(Stream *stream); 199 Error destroyContext(Thread *thread, gl::Context *context); 200 201 void destroySync(Sync *sync); 202 203 bool isInitialized() const; 204 bool isValidConfig(const Config *config) const; 205 bool isValidContext(gl::ContextID contextID) const; 206 bool isValidSurface(SurfaceID surfaceID) const; 207 bool isValidImage(ImageID imageID) const; 208 bool isValidStream(const Stream *stream) const; 209 bool isValidSync(SyncID sync) const; 210 bool isValidNativeWindow(EGLNativeWindowType window) const; 211 212 Error validateClientBuffer(const Config *configuration, 213 EGLenum buftype, 214 EGLClientBuffer clientBuffer, 215 const AttributeMap &attribs) const; 216 Error validateImageClientBuffer(const gl::Context *context, 217 EGLenum target, 218 EGLClientBuffer clientBuffer, 219 const egl::AttributeMap &attribs) const; 220 Error valdiatePixmap(const Config *config, 221 EGLNativePixmapType pixmap, 222 const AttributeMap &attributes) const; 223 224 static bool isValidDisplay(const Display *display); 225 static bool isValidNativeDisplay(EGLNativeDisplayType display); 226 static bool hasExistingWindowSurface(EGLNativeWindowType window); 227 228 bool isDeviceLost() const; 229 bool testDeviceLost(); 230 void notifyDeviceLost(); 231 232 void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); areBlobCacheFuncsSet()233 bool areBlobCacheFuncsSet() const { return mBlobCache.areBlobCacheFuncsSet(); } getBlobCache()234 BlobCache &getBlobCache() { return mBlobCache; } 235 236 static EGLClientBuffer GetNativeClientBuffer(const struct AHardwareBuffer *buffer); 237 static Error CreateNativeClientBuffer(const egl::AttributeMap &attribMap, 238 EGLClientBuffer *eglClientBuffer); 239 240 Error waitClient(const gl::Context *context); 241 Error waitNative(const gl::Context *context, EGLint engine); 242 243 const Caps &getCaps() const; 244 245 const DisplayExtensions &getExtensions() const; 246 const std::string &getExtensionString() const; 247 const std::string &getVendorString() const; 248 const std::string &getVersionString() const; 249 const std::string &getClientAPIString() const; 250 251 std::string getBackendRendererDescription() const; 252 std::string getBackendVendorString() const; 253 std::string getBackendVersionString(bool includeFullVersion) const; 254 255 EGLint programCacheGetAttrib(EGLenum attrib) const; 256 Error programCacheQuery(EGLint index, 257 void *key, 258 EGLint *keysize, 259 void *binary, 260 EGLint *binarysize); 261 Error programCachePopulate(const void *key, 262 EGLint keysize, 263 const void *binary, 264 EGLint binarysize); 265 EGLint programCacheResize(EGLint limit, EGLenum mode); 266 getAttributeMap()267 const AttributeMap &getAttributeMap() const { return mAttributeMap; } getNativeDisplayId()268 EGLNativeDisplayType getNativeDisplayId() const { return mState.displayId; } 269 getImplementation()270 rx::DisplayImpl *getImplementation() const { return mImplementation; } 271 Device *getDevice() const; 272 Surface *getWGLSurface() const; getPlatform()273 EGLenum getPlatform() const { return mPlatform; } 274 275 gl::Version getMaxSupportedESVersion() const; 276 getState()277 const DisplayState &getState() const { return mState; } 278 getFrontendFeatures()279 const angle::FrontendFeatures &getFrontendFeatures() { return mFrontendFeatures; } 280 void overrideFrontendFeatures(const std::vector<std::string> &featureNames, bool enabled); 281 getFeatures()282 const angle::FeatureList &getFeatures() const { return mFeatures; } 283 284 const char *queryStringi(const EGLint name, const EGLint index); 285 286 EGLAttrib queryAttrib(const EGLint attribute); 287 288 angle::ScratchBuffer requestScratchBuffer(); 289 void returnScratchBuffer(angle::ScratchBuffer scratchBuffer); 290 291 angle::ScratchBuffer requestZeroFilledBuffer(); 292 void returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer); 293 294 egl::Error handleGPUSwitch(); 295 egl::Error forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow); 296 297 egl::Error waitUntilWorkScheduled(); 298 getDisplayGlobalMutex()299 angle::SimpleMutex &getDisplayGlobalMutex() { return mDisplayGlobalMutex; } getProgramCacheMutex()300 angle::SimpleMutex &getProgramCacheMutex() { return mProgramCacheMutex; } 301 302 void lockVulkanQueue(); 303 void unlockVulkanQueue(); 304 getMemoryShaderCache()305 gl::MemoryShaderCache *getMemoryShaderCache() { return &mMemoryShaderCache; } 306 307 // Installs LoggingAnnotator as the global DebugAnnotator, for back-ends that do not implement 308 // their own DebugAnnotator. setGlobalDebugAnnotator()309 void setGlobalDebugAnnotator() { gl::InitializeDebugAnnotations(&mAnnotator); } 310 311 bool supportsDmaBufFormat(EGLint format) const; 312 Error queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats); 313 Error queryDmaBufModifiers(EGLint format, 314 EGLint max_modifiers, 315 EGLuint64KHR *modifiers, 316 EGLBoolean *external_only, 317 EGLint *num_modifiers); 318 319 Error querySupportedCompressionRates(const Config *configuration, 320 const AttributeMap &attributes, 321 EGLint *rates, 322 EGLint rate_size, 323 EGLint *num_rates) const; 324 getSingleThreadPool()325 std::shared_ptr<angle::WorkerThreadPool> getSingleThreadPool() const 326 { 327 return mState.singleThreadPool; 328 } getMultiThreadPool()329 std::shared_ptr<angle::WorkerThreadPool> getMultiThreadPool() const 330 { 331 return mState.multiThreadPool; 332 } 333 334 angle::ImageLoadContext getImageLoadContext() const; 335 336 const gl::Context *getContext(gl::ContextID contextID) const; 337 const egl::Surface *getSurface(egl::SurfaceID surfaceID) const; 338 const egl::Image *getImage(egl::ImageID imageID) const; 339 const egl::Sync *getSync(egl::SyncID syncID) const; 340 gl::Context *getContext(gl::ContextID contextID); 341 egl::Surface *getSurface(egl::SurfaceID surfaceID); 342 egl::Image *getImage(egl::ImageID imageID); 343 egl::Sync *getSync(egl::SyncID syncID); 344 getSyncsForCapture()345 const SyncMap &getSyncsForCapture() const { return mSyncMap; } getImagesForCapture()346 const ImageMap &getImagesForCapture() const { return mImageMap; } 347 348 // Initialize thread-local variables used by the Display and its backing implementations. This 349 // includes: 350 // 351 // - The unlocked tail call to be run at the end of the entry point. 352 // - Scratch space for an egl::Error used by the backends (this is not used by all backends, and 353 // access *must* be restricted to backends that use it). 354 // 355 static void InitTLS(); 356 static angle::UnlockedTailCall *GetCurrentThreadUnlockedTailCall(); 357 static Error *GetCurrentThreadErrorScratchSpace(); 358 359 private: 360 Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice); 361 setAttributes(const AttributeMap & attribMap)362 void setAttributes(const AttributeMap &attribMap) { mAttributeMap = attribMap; } 363 void setupDisplayPlatform(rx::DisplayImpl *impl); 364 365 Error restoreLostDevice(); 366 Error releaseContext(gl::Context *context, Thread *thread); 367 Error releaseContextImpl(std::unique_ptr<gl::Context> &&context); 368 std::unique_ptr<gl::Context> eraseContextImpl(gl::Context *context, ContextMap *contexts); 369 370 void initDisplayExtensions(); 371 void initVendorString(); 372 void initVersionString(); 373 void initClientAPIString(); 374 void initializeFrontendFeatures(); 375 376 angle::ScratchBuffer requestScratchBufferImpl(std::vector<angle::ScratchBuffer> *bufferVector); 377 void returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer, 378 std::vector<angle::ScratchBuffer> *bufferVector); 379 380 Error destroyInvalidEglObjects(); 381 382 DisplayState mState; 383 rx::DisplayImpl *mImplementation; 384 angle::ObserverBinding mGPUSwitchedBinding; 385 386 AttributeMap mAttributeMap; 387 388 ConfigSet mConfigSet; 389 390 ImageMap mImageMap; 391 StreamSet mStreamSet; 392 393 SyncMap mSyncMap; 394 395 static constexpr size_t kMaxSyncPoolSizePerType = 32; 396 using SyncPool = angle::FixedVector<std::unique_ptr<Sync>, kMaxSyncPoolSizePerType>; 397 std::map<EGLenum, SyncPool> mSyncPools; 398 399 void destroyImageImpl(Image *image, ImageMap *images); 400 void destroyStreamImpl(Stream *stream, StreamSet *streams); 401 Error destroySurfaceImpl(Surface *surface, SurfaceMap *surfaces); 402 void destroySyncImpl(SyncID syncId, SyncMap *syncs); 403 404 ContextMap mInvalidContextMap; 405 ImageMap mInvalidImageMap; 406 StreamSet mInvalidStreamSet; 407 SurfaceMap mInvalidSurfaceMap; 408 SyncMap mInvalidSyncMap; 409 410 bool mInitialized; 411 412 Caps mCaps; 413 414 DisplayExtensions mDisplayExtensions; 415 std::string mDisplayExtensionString; 416 417 std::string mVendorString; 418 std::string mVersionString; 419 std::string mClientAPIString; 420 421 Device *mDevice; 422 Surface *mSurface; 423 EGLenum mPlatform; 424 angle::LoggingAnnotator mAnnotator; 425 426 // mManagersMutex protects mTextureManager and mSemaphoreManager 427 ContextMutex *mManagersMutex; 428 gl::TextureManager *mTextureManager; 429 gl::SemaphoreManager *mSemaphoreManager; 430 431 BlobCache mBlobCache; 432 gl::MemoryProgramCache mMemoryProgramCache; 433 gl::MemoryShaderCache mMemoryShaderCache; 434 size_t mGlobalTextureShareGroupUsers; 435 size_t mGlobalSemaphoreShareGroupUsers; 436 437 gl::HandleAllocator mImageHandleAllocator; 438 gl::HandleAllocator mSurfaceHandleAllocator; 439 gl::HandleAllocator mSyncHandleAllocator; 440 441 angle::FrontendFeatures mFrontendFeatures; 442 443 angle::FeatureList mFeatures; 444 445 angle::SimpleMutex mScratchBufferMutex; 446 std::vector<angle::ScratchBuffer> mScratchBuffers; 447 std::vector<angle::ScratchBuffer> mZeroFilledBuffers; 448 449 angle::SimpleMutex mDisplayGlobalMutex; 450 angle::SimpleMutex mProgramCacheMutex; 451 452 bool mTerminatedByApi; 453 }; 454 455 } // namespace egl 456 457 #endif // LIBANGLE_DISPLAY_H_ 458