• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 and DisplayEAGL need 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_PLATFORM_APPLE
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     SurfaceMap surfaceMap;
86     angle::FeatureOverrides featureOverrides;
87     EGLNativeDisplayType displayId;
88 
89     // Single-threaded and multithread pools for use by various parts of ANGLE, such as shader
90     // compilation.  These pools are internally synchronized.
91     std::shared_ptr<angle::WorkerThreadPool> singleThreadPool;
92     std::shared_ptr<angle::WorkerThreadPool> multiThreadPool;
93 
94     mutable bool deviceLost;
95 };
96 
97 // Constant coded here as a reasonable limit.
98 constexpr EGLAttrib kProgramCacheSizeAbsoluteMax = 0x4000000;
99 
100 using ImageMap  = angle::HashMap<GLuint, Image *>;
101 using StreamSet = angle::HashSet<Stream *>;
102 using SyncMap   = angle::HashMap<GLuint, std::unique_ptr<Sync>>;
103 
104 class Display final : public LabeledObject,
105                       public angle::ObserverInterface,
106                       public angle::NonCopyable
107 {
108   public:
109     ~Display() override;
110 
111     void setLabel(EGLLabelKHR label) override;
112     EGLLabelKHR getLabel() const override;
113 
114     // Observer implementation.
115     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
116 
117     Error initialize();
118 
119     enum class TerminateReason
120     {
121         Api,
122         InternalCleanup,
123 
124         InvalidEnum,
125         EnumCount = InvalidEnum,
126     };
127     Error terminate(Thread *thread, TerminateReason terminateReason);
128 
129 #if ANGLE_USE_DISPLAY_PREPARE_FOR_CALL
130     // Called before all display state dependent EGL functions. Backends can set up, for example,
131     // thread-specific backend state through this function. Not called for functions that do not
132     // need the state.
133     Error prepareForCall();
134 #endif
135 
136     // Called on eglReleaseThread. Backends can tear down thread-specific backend state through
137     // this function.
138     Error releaseThread();
139 
140     static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
141     static Display *GetDisplayFromNativeDisplay(EGLenum platform,
142                                                 EGLNativeDisplayType nativeDisplay,
143                                                 const AttributeMap &attribMap);
144     static Display *GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay);
145 
146     using EglDisplaySet = angle::HashSet<Display *>;
147     static EglDisplaySet GetEglDisplaySet();
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 EGLenum clientType,
183                         const AttributeMap &attribs,
184                         gl::Context **outContext);
185 
186     Error createSync(const gl::Context *currentContext,
187                      EGLenum type,
188                      const AttributeMap &attribs,
189                      Sync **outSync);
190 
191     Error makeCurrent(Thread *thread,
192                       gl::Context *previousContext,
193                       Surface *drawSurface,
194                       Surface *readSurface,
195                       gl::Context *context);
196 
197     Error destroySurface(Surface *surface);
198     void destroyImage(Image *image);
199     void destroyStream(Stream *stream);
200     Error destroyContext(Thread *thread, gl::Context *context);
201 
202     void destroySync(Sync *sync);
203 
204     bool isInitialized() const;
205     bool isValidConfig(const Config *config) const;
206     bool isValidContext(gl::ContextID contextID) const;
207     bool isValidSurface(SurfaceID surfaceID) const;
208     bool isValidImage(ImageID imageID) const;
209     bool isValidStream(const Stream *stream) const;
210     bool isValidSync(SyncID sync) const;
211     bool isValidNativeWindow(EGLNativeWindowType window) const;
212 
213     Error validateClientBuffer(const Config *configuration,
214                                EGLenum buftype,
215                                EGLClientBuffer clientBuffer,
216                                const AttributeMap &attribs) const;
217     Error validateImageClientBuffer(const gl::Context *context,
218                                     EGLenum target,
219                                     EGLClientBuffer clientBuffer,
220                                     const egl::AttributeMap &attribs) const;
221     Error valdiatePixmap(const Config *config,
222                          EGLNativePixmapType pixmap,
223                          const AttributeMap &attributes) const;
224 
225     static bool isValidDisplay(const Display *display);
226     static bool isValidNativeDisplay(EGLNativeDisplayType display);
227     static bool hasExistingWindowSurface(EGLNativeWindowType window);
228 
229     bool isDeviceLost() const;
230     bool testDeviceLost();
231     void notifyDeviceLost();
232 
233     void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
areBlobCacheFuncsSet()234     bool areBlobCacheFuncsSet() const { return mBlobCache.areBlobCacheFuncsSet(); }
getBlobCache()235     BlobCache &getBlobCache() { return mBlobCache; }
236 
237     static EGLClientBuffer GetNativeClientBuffer(const struct AHardwareBuffer *buffer);
238     static Error CreateNativeClientBuffer(const egl::AttributeMap &attribMap,
239                                           EGLClientBuffer *eglClientBuffer);
240 
241     Error waitClient(const gl::Context *context);
242     Error waitNative(const gl::Context *context, EGLint engine);
243 
244     const Caps &getCaps() const;
245 
246     const DisplayExtensions &getExtensions() const;
247     const std::string &getExtensionString() const;
248     const std::string &getVendorString() const;
249     const std::string &getVersionString() const;
250     const std::string &getClientAPIString() const;
251 
252     std::string getBackendRendererDescription() const;
253     std::string getBackendVendorString() const;
254     std::string getBackendVersionString(bool includeFullVersion) const;
255 
256     EGLint programCacheGetAttrib(EGLenum attrib) const;
257     Error programCacheQuery(EGLint index,
258                             void *key,
259                             EGLint *keysize,
260                             void *binary,
261                             EGLint *binarysize);
262     Error programCachePopulate(const void *key,
263                                EGLint keysize,
264                                const void *binary,
265                                EGLint binarysize);
266     EGLint programCacheResize(EGLint limit, EGLenum mode);
267 
getAttributeMap()268     const AttributeMap &getAttributeMap() const { return mAttributeMap; }
getNativeDisplayId()269     EGLNativeDisplayType getNativeDisplayId() const { return mState.displayId; }
270 
getImplementation()271     rx::DisplayImpl *getImplementation() const { return mImplementation; }
272     Device *getDevice() const;
273     Surface *getWGLSurface() const;
getPlatform()274     EGLenum getPlatform() const { return mPlatform; }
275 
276     gl::Version getMaxSupportedESVersion() const;
277 
getState()278     const DisplayState &getState() const { return mState; }
279 
getFrontendFeatures()280     const angle::FrontendFeatures &getFrontendFeatures() { return mFrontendFeatures; }
281     void overrideFrontendFeatures(const std::vector<std::string> &featureNames, bool enabled);
282 
getFeatures()283     const angle::FeatureList &getFeatures() const { return mFeatures; }
284 
285     const char *queryStringi(const EGLint name, const EGLint index);
286 
287     EGLAttrib queryAttrib(const EGLint attribute);
288 
289     angle::ScratchBuffer requestScratchBuffer();
290     void returnScratchBuffer(angle::ScratchBuffer scratchBuffer);
291 
292     angle::ScratchBuffer requestZeroFilledBuffer();
293     void returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer);
294 
295     egl::Error handleGPUSwitch();
296     egl::Error forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow);
297 
298     egl::Error waitUntilWorkScheduled();
299 
getDisplayGlobalMutex()300     angle::SimpleMutex &getDisplayGlobalMutex() { return mDisplayGlobalMutex; }
getProgramCacheMutex()301     angle::SimpleMutex &getProgramCacheMutex() { return mProgramCacheMutex; }
302 
getMemoryShaderCache()303     gl::MemoryShaderCache *getMemoryShaderCache() { return &mMemoryShaderCache; }
304 
305     // Installs LoggingAnnotator as the global DebugAnnotator, for back-ends that do not implement
306     // their own DebugAnnotator.
setGlobalDebugAnnotator()307     void setGlobalDebugAnnotator() { gl::InitializeDebugAnnotations(&mAnnotator); }
308 
309     bool supportsDmaBufFormat(EGLint format) const;
310     Error queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats);
311     Error queryDmaBufModifiers(EGLint format,
312                                EGLint max_modifiers,
313                                EGLuint64KHR *modifiers,
314                                EGLBoolean *external_only,
315                                EGLint *num_modifiers);
316 
getSingleThreadPool()317     std::shared_ptr<angle::WorkerThreadPool> getSingleThreadPool() const
318     {
319         return mState.singleThreadPool;
320     }
getMultiThreadPool()321     std::shared_ptr<angle::WorkerThreadPool> getMultiThreadPool() const
322     {
323         return mState.multiThreadPool;
324     }
325 
326     angle::ImageLoadContext getImageLoadContext() const;
327 
328     const gl::Context *getContext(gl::ContextID contextID) const;
329     const egl::Surface *getSurface(egl::SurfaceID surfaceID) const;
330     const egl::Image *getImage(egl::ImageID imageID) const;
331     const egl::Sync *getSync(egl::SyncID syncID) const;
332     gl::Context *getContext(gl::ContextID contextID);
333     egl::Surface *getSurface(egl::SurfaceID surfaceID);
334     egl::Image *getImage(egl::ImageID imageID);
335     egl::Sync *getSync(egl::SyncID syncID);
336 
getSyncsForCapture()337     const SyncMap &getSyncsForCapture() const { return mSyncMap; }
getImagesForCapture()338     const ImageMap &getImagesForCapture() const { return mImageMap; }
339 
340     // Initialize thread-local variables used by the Display and its backing implementations.  This
341     // includes:
342     //
343     // - The unlocked tail call to be run at the end of the entry point.
344     // - Scratch space for an egl::Error used by the backends (this is not used by all backends, and
345     //   access *must* be restricted to backends that use it).
346     //
347     static void InitTLS();
348     static angle::UnlockedTailCall *GetCurrentThreadUnlockedTailCall();
349     static Error *GetCurrentThreadErrorScratchSpace();
350 
351   private:
352     Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice);
353 
setAttributes(const AttributeMap & attribMap)354     void setAttributes(const AttributeMap &attribMap) { mAttributeMap = attribMap; }
355     void setupDisplayPlatform(rx::DisplayImpl *impl);
356 
357     Error restoreLostDevice();
358     Error releaseContext(gl::Context *context, Thread *thread);
359     Error releaseContextImpl(gl::Context *context, ContextMap *contexts);
360 
361     void initDisplayExtensions();
362     void initVendorString();
363     void initVersionString();
364     void initClientAPIString();
365     void initializeFrontendFeatures();
366 
367     angle::ScratchBuffer requestScratchBufferImpl(std::vector<angle::ScratchBuffer> *bufferVector);
368     void returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,
369                                  std::vector<angle::ScratchBuffer> *bufferVector);
370 
371     Error destroyInvalidEglObjects();
372 
373     DisplayState mState;
374     rx::DisplayImpl *mImplementation;
375     angle::ObserverBinding mGPUSwitchedBinding;
376 
377     AttributeMap mAttributeMap;
378 
379     ConfigSet mConfigSet;
380 
381     ImageMap mImageMap;
382     StreamSet mStreamSet;
383 
384     SyncMap mSyncMap;
385 
386     static constexpr size_t kMaxSyncPoolSizePerType = 32;
387     using SyncPool = angle::FixedVector<std::unique_ptr<Sync>, kMaxSyncPoolSizePerType>;
388     std::map<EGLenum, SyncPool> mSyncPools;
389 
390     void destroyImageImpl(Image *image, ImageMap *images);
391     void destroyStreamImpl(Stream *stream, StreamSet *streams);
392     Error destroySurfaceImpl(Surface *surface, SurfaceMap *surfaces);
393     void destroySyncImpl(SyncID syncId, SyncMap *syncs);
394 
395     ContextMap mInvalidContextMap;
396     ImageMap mInvalidImageMap;
397     StreamSet mInvalidStreamSet;
398     SurfaceMap mInvalidSurfaceMap;
399     SyncMap mInvalidSyncMap;
400 
401     bool mInitialized;
402 
403     Caps mCaps;
404 
405     DisplayExtensions mDisplayExtensions;
406     std::string mDisplayExtensionString;
407 
408     std::string mVendorString;
409     std::string mVersionString;
410     std::string mClientAPIString;
411 
412     Device *mDevice;
413     Surface *mSurface;
414     EGLenum mPlatform;
415     angle::LoggingAnnotator mAnnotator;
416 
417     // mManagersMutex protects mTextureManager and mSemaphoreManager
418     ContextMutex *mManagersMutex;
419     gl::TextureManager *mTextureManager;
420     gl::SemaphoreManager *mSemaphoreManager;
421 
422     BlobCache mBlobCache;
423     gl::MemoryProgramCache mMemoryProgramCache;
424     gl::MemoryShaderCache mMemoryShaderCache;
425     size_t mGlobalTextureShareGroupUsers;
426     size_t mGlobalSemaphoreShareGroupUsers;
427 
428     gl::HandleAllocator mImageHandleAllocator;
429     gl::HandleAllocator mSurfaceHandleAllocator;
430     gl::HandleAllocator mSyncHandleAllocator;
431 
432     angle::FrontendFeatures mFrontendFeatures;
433 
434     angle::FeatureList mFeatures;
435 
436     angle::SimpleMutex mScratchBufferMutex;
437     std::vector<angle::ScratchBuffer> mScratchBuffers;
438     std::vector<angle::ScratchBuffer> mZeroFilledBuffers;
439 
440     angle::SimpleMutex mDisplayGlobalMutex;
441     angle::SimpleMutex mProgramCacheMutex;
442 
443     bool mTerminatedByApi;
444 };
445 
446 }  // namespace egl
447 
448 #endif  // LIBANGLE_DISPLAY_H_
449