• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011-2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef _LIBRENDER_FRAMEBUFFER_H
17 #define _LIBRENDER_FRAMEBUFFER_H
18 
19 #include <EGL/egl.h>
20 #include <GLES2/gl2.h>
21 #include <GLES2/gl2ext.h>
22 #include <stdint.h>
23 
24 #include <array>
25 #include <functional>
26 #include <map>
27 #include <memory>
28 #include <optional>
29 #include <unordered_map>
30 #include <unordered_set>
31 
32 #include "Buffer.h"
33 #include "Compositor.h"
34 #include "Display.h"
35 #include "DisplaySurface.h"
36 #include "Hwc2.h"
37 #include "PostCommands.h"
38 #include "PostWorker.h"
39 #include "ReadbackWorker.h"
40 #include "VsyncThread.h"
41 #include "aemu/base/AsyncResult.h"
42 #include "aemu/base/EventNotificationSupport.h"
43 #include "aemu/base/HealthMonitor.h"
44 #include "aemu/base/ManagedDescriptor.hpp"
45 #include "aemu/base/Metrics.h"
46 #include "aemu/base/files/Stream.h"
47 #include "aemu/base/synchronization/Lock.h"
48 #include "aemu/base/synchronization/MessageChannel.h"
49 #include "aemu/base/threads/Thread.h"
50 #include "aemu/base/threads/WorkerThread.h"
51 #include "gl/BufferGl.h"
52 #include "gl/ColorBufferGl.h"
53 #include "gl/CompositorGl.h"
54 #include "gl/DisplaySurfaceGl.h"
55 #include "gl/EmulatedEglConfig.h"
56 #include "gl/EmulatedEglContext.h"
57 #include "gl/EmulatedEglImage.h"
58 #include "gl/EmulatedEglWindowSurface.h"
59 #include "gl/EmulationGl.h"
60 #include "gl/GLESVersionDetector.h"
61 #include "gl/TextureDraw.h"
62 #include "render-utils/Renderer.h"
63 #include "render-utils/virtio_gpu_ops.h"
64 #include "render_api.h"
65 #include "snapshot/common.h"
66 #include "utils/RenderDoc.h"
67 #include "vulkan/vk_util.h"
68 
69 namespace gfxstream {
70 namespace vk {
71 class DisplayVk;
72 }  // namespace vk
73 }  // namespace gfxstream
74 
75 namespace gfxstream {
76 
77 using android::base::CreateMetricsLogger;
78 using emugl::HealthMonitor;
79 using emugl::MetricsLogger;
80 
81 struct BufferRef {
82     BufferPtr buffer;
83 };
84 
85 class ProcessResources {
86    public:
87     // We only allow ProcessResources to be created on the heap, because the pointer to
88     // mSequenceNumber shouldn't change until ProcessResources is destroyed.
create()89     static std::unique_ptr<ProcessResources> create() {
90         return std::unique_ptr<ProcessResources>(new ProcessResources());
91     }
92     DISALLOW_COPY_ASSIGN_AND_MOVE(ProcessResources);
93 
94     ~ProcessResources() = default;
getSequenceNumberPtr()95     std::atomic<uint32_t>* getSequenceNumberPtr() const {
96         return &mSequenceNumber;
97     }
98 
99    private:
ProcessResources()100     ProcessResources() : mSequenceNumber(0) {}
101     mutable std::atomic<uint32_t> mSequenceNumber;
102 };
103 
104 typedef std::unordered_map<uint64_t, gl::EmulatedEglWindowSurfaceSet>
105     ProcOwnedEmulatedEglWindowSurfaces;
106 
107 typedef std::unordered_map<uint64_t, gl::EmulatedEglContextSet> ProcOwnedEmulatedEglContexts;
108 
109 typedef std::unordered_map<uint64_t, ColorBufferSet> ProcOwnedColorBuffers;
110 
111 typedef std::unordered_map<HandleType, BufferRef> BufferMap;
112 typedef std::unordered_multiset<HandleType> BufferSet;
113 typedef std::unordered_map<uint64_t, BufferSet> ProcOwnedBuffers;
114 
115 typedef std::unordered_map<uint64_t, gl::EmulatedEglImageSet> ProcOwnedEmulatedEGLImages;
116 
117 typedef std::unordered_map<void*, std::function<void()>> CallbackMap;
118 typedef std::unordered_map<uint64_t, CallbackMap> ProcOwnedCleanupCallbacks;
119 
120 // The FrameBuffer class holds the global state of the emulation library on
121 // top of the underlying EGL/GLES implementation. It should probably be
122 // named "Display" instead of "FrameBuffer".
123 //
124 // There is only one global instance, that can be retrieved with getFB(),
125 // and which must be previously setup by calling initialize().
126 //
127 class FrameBuffer : public android::base::EventNotificationSupport<FrameBufferChangeEvent> {
128    public:
129     // Initialize the global instance.
130     // |width| and |height| are the dimensions of the emulator GPU display
131     // in pixels. |useSubWindow| is true to indicate that the caller
132     // will use setupSubWindow() to let EmuGL display the GPU content in its
133     // own sub-windows. If false, this means the caller will use
134     // setPostCallback() instead to retrieve the content.
135     // Returns true on success, false otherwise.
136     static bool initialize(int width, int height, bool useSubWindow,
137                            bool egl2egl);
138 
139     // Finalize the instance.
140     static void finalize();
141 
142     // Setup a sub-window to display the content of the emulated GPU
143     // on-top of an existing UI window. |p_window| is the platform-specific
144     // parent window handle. |wx|, |wy|, |ww| and |wh| are the
145     // dimensions in pixels of the sub-window, relative to the parent window's
146     // coordinate. |fbw| and |fbh| are the dimensions used to initialize
147     // the framebuffer, which may be different from the dimensions of the
148     // sub-window (in which case scaling will be applied automatically).
149     // |dpr| is the device pixel ratio of the monitor, which is needed for
150     // proper panning on high-density displays (like retina)
151     // |zRot| is a rotation angle in degrees, (clockwise in the Y-upwards GL
152     // coordinate space).
153     //
154     // If a sub-window already exists, this function updates the subwindow
155     // and framebuffer properties to match the given values.
156     //
157     // Return true on success, false otherwise.
158     //
159     // NOTE: This can return false for software-only EGL engines like OSMesa.
160     bool setupSubWindow(FBNativeWindowType p_window, int wx, int wy, int ww,
161                         int wh, int fbw, int fbh, float dpr, float zRot,
162                         bool deleteExisting, bool hideWindow);
163 
164     // Remove the sub-window created by setupSubWindow(), if any.
165     // Return true on success, false otherwise.
166     bool removeSubWindow();
167 
168     // Return a pointer to the global instance. initialize() must be called
169     // previously, or this will return NULL.
getFB()170     static FrameBuffer* getFB() { return s_theFrameBuffer; }
171 
172     // Wait for a FrameBuffer instance to be initialized and ready to use.
173     // This function blocks the caller until there is a valid initialized
174     // object in getFB() and
175     static void waitUntilInitialized();
176 
177     // Return the emulated GPU display width in pixels.
getWidth()178     int getWidth() const { return m_framebufferWidth; }
179 
180     // Return the emulated GPU display height in pixels.
getHeight()181     int getHeight() const { return m_framebufferHeight; }
182 
183     // Return the list of configs available from this display.
184     const gl::EmulatedEglConfigList* getConfigs() const;
185 
186     // Set a callback that will be called each time the emulated GPU content
187     // is updated. This can be relatively slow with host-based GPU emulation,
188     // so only do this when you need to.
189     void setPostCallback(Renderer::OnPostCallback onPost, void* onPostContext, uint32_t displayId,
190                          bool useBgraReadback = false);
191 
192     // Retrieve the GL strings of the underlying EGL/GLES implementation.
193     // On return, |*vendor|, |*renderer| and |*version| will point to strings
194     // that are owned by the instance (and must not be freed by the caller).
getGLStrings(const char ** vendor,const char ** renderer,const char ** version)195     void getGLStrings(const char** vendor, const char** renderer,
196                       const char** version) const {
197         *vendor = m_graphicsAdapterVendor.c_str();
198         *renderer = m_graphicsAdapterName.c_str();
199         *version = m_graphicsApiVersion.c_str();
200     }
201 
202     // Create a new EmulatedEglContext instance for this display instance.
203     // |p_config| is the index of one of the configs returned by getConfigs().
204     // |p_share| is either EGL_NO_CONTEXT or the handle of a shared context.
205     // |version| specifies the GLES version as a GLESApi enum.
206     // Return a new handle value, which will be 0 in case of error.
207     HandleType createEmulatedEglContext(int p_config, HandleType p_share,
208                                         gl::GLESApi version = gl::GLESApi_CM);
209 
210     // Destroy a given EmulatedEglContext instance. |p_context| is its handle
211     // value as returned by createEmulatedEglContext().
212     void destroyEmulatedEglContext(HandleType p_context);
213 
214     // Create a new EmulatedEglWindowSurface instance from this display instance.
215     // |p_config| is the index of one of the configs returned by getConfigs().
216     // |p_width| and |p_height| are the window dimensions in pixels.
217     // Return a new handle value, or 0 in case of error.
218     HandleType createEmulatedEglWindowSurface(int p_config, int p_width, int p_height);
219 
220     // Destroy a given EmulatedEglWindowSurface instance. |p_surcace| is its
221     // handle value as returned by createEmulatedEglWindowSurface().
222     void destroyEmulatedEglWindowSurface(HandleType p_surface);
223 
224     // Returns the set of ColorBuffers destroyed (for further cleanup)
225     std::vector<HandleType> destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface);
226 
227     void createEmulatedEglFenceSync(EGLenum type,
228                                     int destroyWhenSignaled,
229                                     uint64_t* outSync = nullptr,
230                                     uint64_t* outSyncThread = nullptr);
231 
232     // Create a new ColorBuffer instance from this display instance.
233     // |p_width| and |p_height| are its dimensions in pixels.
234     // |p_internalFormat| is the OpenGL format of this color buffer.
235     // |p_frameworkFormat| describes the Android frameework format of this
236     // color buffer, if differing from |p_internalFormat|.
237     // See ColorBuffer::create() for
238     // list of valid values. Note that ColorBuffer instances are reference-
239     // counted. Use openColorBuffer / closeColorBuffer to operate on the
240     // internal count.
241     HandleType createColorBuffer(int p_width, int p_height,
242                                  GLenum p_internalFormat,
243                                  FrameworkFormat p_frameworkFormat);
244     // Variant of createColorBuffer except with a particular
245     // handle already assigned. This is for use with
246     // virtio-gpu's RESOURCE_CREATE ioctl.
247     void createColorBufferWithHandle(int p_width, int p_height, GLenum p_internalFormat,
248                                      FrameworkFormat p_frameworkFormat, HandleType handle);
249 
250     // Create a new data Buffer instance from this display instance.
251     // The buffer will be backed by a VkBuffer and VkDeviceMemory (if Vulkan
252     // is available).
253     // |size| is the requested size of Buffer in bytes.
254     // |memoryProperty| is the requested memory property bits of the device
255     // memory.
256     HandleType createBuffer(uint64_t size, uint32_t memoryProperty);
257 
258     // Variant of createBuffer except with a particular handle already
259     // assigned and using device local memory. This is for use with
260     // virtio-gpu's RESOURCE_CREATE ioctl for BLOB resources.
261     void createBufferWithHandle(uint64_t size, HandleType handle);
262 
263     // Call this function when a render thread terminates to destroy all
264     // resources it created. Necessary to avoid leaking host resources
265     // when a guest application crashes, for example.
266     void drainGlRenderThreadResources();
267 
268     // Call this function when a render thread terminates to destroy all
269     // the remaining contexts it created. Necessary to avoid leaking host
270     // contexts when a guest application crashes, for example.
271     void drainGlRenderThreadContexts();
272 
273     // Call this function when a render thread terminates to destroy all
274     // remaining window surface it created. Necessary to avoid leaking
275     // host buffers when a guest application crashes, for example.
276     void drainGlRenderThreadSurfaces();
277 
278     // Increment the reference count associated with a given ColorBuffer
279     // instance. |p_colorbuffer| is its handle value as returned by
280     // createColorBuffer().
281     int openColorBuffer(HandleType p_colorbuffer);
282 
283     // Decrement the reference count associated with a given ColorBuffer
284     // instance. |p_colorbuffer| is its handle value as returned by
285     // createColorBuffer(). Note that if the reference count reaches 0,
286     // the instance is destroyed automatically.
287     void closeColorBuffer(HandleType p_colorbuffer);
288 
289     // Destroy a Buffer created previously. |p_buffer| is its handle value as
290     // returned by createBuffer().
291     void closeBuffer(HandleType p_colorbuffer);
292 
293     // The caller mustn't refer to this puid before this function returns, i.e. the creation of the
294     // host process pipe must be blocked until this function returns.
295     void createGraphicsProcessResources(uint64_t puid);
296     // The process resource is returned so that we can destroy it on a separate thread.
297     std::unique_ptr<ProcessResources> removeGraphicsProcessResources(uint64_t puid);
298     // TODO(kaiyili): retire cleanupProcGLObjects in favor of removeGraphicsProcessResources.
299     void cleanupProcGLObjects(uint64_t puid);
300 
301     // Equivalent for eglMakeCurrent() for the current display.
302     // |p_context|, |p_drawSurface| and |p_readSurface| are the handle values
303     // of the context, the draw surface and the read surface, respectively.
304     // Returns true on success, false on failure.
305     // Note: if all handle values are 0, this is an unbind operation.
306     bool bindContext(HandleType p_context, HandleType p_drawSurface,
307                      HandleType p_readSurface);
308 
309     // Return a render context pointer from its handle
310     gl::EmulatedEglContextPtr getContext_locked(HandleType p_context);
311 
312     // Return a color buffer pointer from its handle
313     gl::EmulatedEglWindowSurfacePtr getWindowSurface_locked(HandleType p_windowsurface);
314 
315     // Attach a ColorBuffer to a EmulatedEglWindowSurface instance.
316     // See the documentation for EmulatedEglWindowSurface::setColorBuffer().
317     // |p_surface| is the target EmulatedEglWindowSurface's handle value.
318     // |p_colorbuffer| is the ColorBuffer handle value.
319     // Returns true on success, false otherwise.
320     bool setEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface,
321                                                 HandleType p_colorbuffer);
322 
323     // Copy the content of a EmulatedEglWindowSurface's Pbuffer to its attached
324     // ColorBuffer. See the documentation for
325     // EmulatedEglWindowSurface::flushColorBuffer().
326     // |p_surface| is the target WindowSurface's handle value.
327     // Returns true on success, false on failure.
328     bool flushEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface);
329 
330     // Retrieves the color buffer handle associated with |p_surface|.
331     // Returns 0 if there is no such handle.
332     HandleType getEmulatedEglWindowSurfaceColorBufferHandle(HandleType p_surface);
333 
334     // Bind the current context's EGL_TEXTURE_2D texture to a ColorBuffer
335     // instance's EGLImage. This is intended to implement
336     // glEGLImageTargetTexture2DOES() for all GLES versions.
337     // |p_colorbuffer| is the ColorBuffer's handle value.
338     // Returns true on success, false on failure.
339     bool bindColorBufferToTexture(HandleType p_colorbuffer);
340     bool bindColorBufferToTexture2(HandleType p_colorbuffer);
341 
342     // Bind the current context's EGL_RENDERBUFFER_OES render buffer to this
343     // ColorBuffer's EGLImage. This is intended to implement
344     // glEGLImageTargetRenderbufferStorageOES() for all GLES versions.
345     // |p_colorbuffer| is the ColorBuffer's handle value.
346     // Returns true on success, false on failure.
347     bool bindColorBufferToRenderbuffer(HandleType p_colorbuffer);
348 
349     // Read the content of a given Buffer into client memory.
350     // |p_buffer| is the Buffer's handle value.
351     // |offset| and |size| are the position and size of a slice of the buffer
352     // that will be read.
353     // |bytes| is the address of a caller-provided buffer that will be filled
354     // with the buffer data.
355     void readBuffer(HandleType p_buffer, uint64_t offset, uint64_t size, void* bytes);
356 
357     // Read the content of a given ColorBuffer into client memory.
358     // |p_colorbuffer| is the ColorBuffer's handle value. Similar
359     // to glReadPixels(), this can be a slow operation.
360     // |x|, |y|, |width| and |height| are the position and dimensions of
361     // a rectangle whose pixel values will be transfered to the host.
362     // |format| indicates the format of the pixel data, e.g. GL_RGB or GL_RGBA.
363     // |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE.
364     // |pixels| is the address of a caller-provided buffer that will be filled
365     // with the pixel data.
366     void readColorBuffer(HandleType p_colorbuffer, int x, int y, int width,
367                          int height, GLenum format, GLenum type, void* pixels);
368 
369     // Read the content of a given YUV420_888 ColorBuffer into client memory.
370     // |p_colorbuffer| is the ColorBuffer's handle value. Similar
371     // to glReadPixels(), this can be a slow operation.
372     // |x|, |y|, |width| and |height| are the position and dimensions of
373     // a rectangle whose pixel values will be transfered to the host.
374     // |pixels| is the address of a caller-provided buffer that will be filled
375     // with the pixel data.
376     // |pixles_size| is the size of buffer
377     void readColorBufferYUV(HandleType p_colorbuffer, int x, int y, int width,
378                             int height, void* pixels, uint32_t pixels_size);
379 
380     // create a Y texture and a UV texture with width and height, the created
381     // texture ids are stored in textures respectively
382     void createYUVTextures(uint32_t type, uint32_t count, int width, int height,
383                            uint32_t* output);
384     void destroyYUVTextures(uint32_t type, uint32_t count, uint32_t* textures);
385     void updateYUVTextures(uint32_t type, uint32_t* textures, void* privData,
386                            void* func);
387     void swapTexturesAndUpdateColorBuffer(uint32_t colorbufferhandle, int x,
388                                           int y, int width, int height,
389                                           uint32_t format, uint32_t type,
390                                           uint32_t texture_type,
391                                           uint32_t* textures);
392 
393     // Update the content of a given Buffer from client data.
394     // |p_buffer| is the Buffer's handle value.
395     // |offset| and |size| are the position and size of a slice of the buffer
396     // that will be updated.
397     // |bytes| is the address of a caller-provided buffer containing the new
398     // buffer data.
399     bool updateBuffer(HandleType p_buffer, uint64_t offset, uint64_t size, void* pixels);
400 
401     // Update the content of a given ColorBuffer from client data.
402     // |p_colorbuffer| is the ColorBuffer's handle value. Similar
403     // to glReadPixels(), this can be a slow operation.
404     // |x|, |y|, |width| and |height| are the position and dimensions of
405     // a rectangle whose pixel values will be transfered to the GPU
406     // |format| indicates the format of the OpenGL buffer, e.g. GL_RGB or
407     // GL_RGBA. |frameworkFormat| indicates the format of the pixel data; if
408     // FRAMEWORK_FORMAT_GL_COMPATIBLE, |format| (OpenGL format) is used.
409     // Otherwise, explicit conversion to |format| is needed.
410     // |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE.
411     // |pixels| is the address of a buffer containing the new pixel data.
412     // Returns true on success, false otherwise.
413     bool updateColorBuffer(HandleType p_colorbuffer, int x, int y, int width,
414                            int height, GLenum format, GLenum type,
415                            void* pixels);
416     bool updateColorBufferFromFrameworkFormat(HandleType p_colorbuffer, int x, int y, int width,
417                                               int height, FrameworkFormat fwkFormat, GLenum format,
418                                               GLenum type, void* pixels);
419 
420     // Reads back the raw color buffer to |pixels|
421     // if |pixels| is not null.
422     // Always returns in |numBytes| how many bytes were
423     // planned to be transmitted.
424     // |numBytes| is not an input parameter;
425     // fewer or more bytes cannot be specified.
426     // If the framework format is YUV, it will read
427     // back as raw YUV data.
428     bool readColorBufferContents(HandleType p_colorbuffer, size_t* numBytes,
429                                  void* pixels);
430 
431     bool getColorBufferInfo(HandleType p_colorbuffer, int* width, int* height,
432                             GLint* internalformat,
433                             FrameworkFormat* frameworkFormat = nullptr);
434     bool getBufferInfo(HandleType p_buffer, int* size);
435 
436     // Display the content of a given ColorBuffer into the framebuffer's
437     // sub-window. |p_colorbuffer| is a handle value.
438     // |needLockAndBind| is used to indicate whether the operation requires
439     // acquiring/releasing the FrameBuffer instance's lock and binding the
440     // contexts. It should be |false| only when called internally.
441     bool post(HandleType p_colorbuffer, bool needLockAndBind = true);
442     // The callback will always be called; however, the callback may not be called
443     // until after this function has returned. If the callback is deferred, then it
444     // will be dispatched to run on SyncThread.
445     void postWithCallback(HandleType p_colorbuffer, Post::CompletionCallback callback, bool needLockAndBind = true);
hasGuestPostedAFrame()446     bool hasGuestPostedAFrame() { return m_guestPostedAFrame; }
resetGuestPostedAFrame()447     void resetGuestPostedAFrame() { m_guestPostedAFrame = false; }
448 
449     // Runs the post callback with |pixels| (good for when the readback
450     // happens in a separate place)
451     void doPostCallback(void* pixels, uint32_t displayId);
452 
453     void getPixels(void* pixels, uint32_t bytes, uint32_t displayId);
454     void flushReadPipeline(int displayId);
455     void ensureReadbackWorker();
456 
457     bool asyncReadbackSupported();
458     Renderer::ReadPixelsCallback getReadPixelsCallback();
459     Renderer::FlushReadPixelPipeline getFlushReadPixelPipeline();
460 
461     // Re-post the last ColorBuffer that was displayed through post().
462     // This is useful if you detect that the sub-window content needs to
463     // be re-displayed for any reason.
464     bool repost(bool needLockAndBind = true);
465 
466     gl::EmulationGl& getEmulationGl();
hasEmulationGl()467     bool hasEmulationGl() const { return m_emulationGl != nullptr; }
468 
469     // Return the host EGLDisplay used by this instance.
470     EGLDisplay getDisplay() const;
471     EGLSurface getWindowSurface() const;
472     EGLContext getContext() const;
473     EGLConfig getConfig() const;
474     ContextHelper* getPbufferSurfaceContextHelper() const;
475 
476     // Change the rotation of the displayed GPU sub-window.
setDisplayRotation(float zRot)477     void setDisplayRotation(float zRot) {
478         if (zRot != m_zRot) {
479             m_zRot = zRot;
480             repost();
481         }
482     }
483 
484     // Changes what coordinate of this framebuffer will be displayed at the
485     // corner of the GPU sub-window. Specifically, |px| and |py| = 0 means
486     // align the bottom-left of the framebuffer with the bottom-left of the
487     // sub-window, and |px| and |py| = 1 means align the top right of the
488     // framebuffer with the top right of the sub-window. Intermediate values
489     // interpolate between these states.
setDisplayTranslation(float px,float py)490     void setDisplayTranslation(float px, float py) {
491         // Sanity check the values to ensure they are between 0 and 1
492         const float x = px > 1.f ? 1.f : (px < 0.f ? 0.f : px);
493         const float y = py > 1.f ? 1.f : (py < 0.f ? 0.f : py);
494         if (x != m_px || y != m_py) {
495             m_px = x;
496             m_py = y;
497             repost();
498         }
499     }
500 
501     // Return a TextureDraw instance that can be used with this surfaces
502     // and windows created by this instance.
503     gl::TextureDraw* getTextureDraw() const;
504 
505     // Create an eglImage and return its handle.  Reference:
506     // https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
507     HandleType createEmulatedEglImage(HandleType context, EGLenum target,
508                                       GLuint buffer);
509     // Call the implementation of eglDestroyImageKHR, return if succeeds or
510     // not. Reference:
511     // https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
512     EGLBoolean destroyEmulatedEglImage(HandleType image);
513 
lockContextStructureRead()514     void lockContextStructureRead() { m_contextStructureLock.lockRead(); }
unlockContextStructureRead()515     void unlockContextStructureRead() { m_contextStructureLock.unlockRead(); }
516 
517     // For use with sync threads and otherwise, any time we need a GL context
518     // not specifically for drawing, but to obtain certain things about
519     // GL state.
520     // It can be unsafe / leaky to change the structure of contexts
521     // outside the facilities the FrameBuffer class provides.
522     void createTrivialContext(HandleType shared, HandleType* contextOut,
523                               HandleType* surfOut);
524     // createTrivialContext(), but with a m_pbufContext
525     // as shared, and not adding itself to the context map at all.
526     void createSharedTrivialContext(EGLContext* contextOut, EGLSurface* surfOut);
527     void destroySharedTrivialContext(EGLContext context, EGLSurface surf);
528 
setShuttingDown()529     void setShuttingDown() { m_shuttingDown = true; }
isShuttingDown()530     bool isShuttingDown() const { return m_shuttingDown; }
531     bool compose(uint32_t bufferSize, void* buffer, bool post = true);
532     // When false is returned, the callback won't be called. The callback will
533     // be called on the PostWorker thread without blocking the current thread.
534     AsyncResult composeWithCallback(uint32_t bufferSize, void* buffer,
535                              Post::CompletionCallback callback);
536 
537     ~FrameBuffer();
538 
539     void onSave(android::base::Stream* stream,
540                 const android::snapshot::ITextureSaverPtr& textureSaver);
541     bool onLoad(android::base::Stream* stream,
542                 const android::snapshot::ITextureLoaderPtr& textureLoader);
543 
544     // lock and unlock handles (EmulatedEglContext, ColorBuffer, EmulatedEglWindowSurface)
545     void lock();
546     void unlock();
547 
548     gl::GLESDispatchMaxVersion getMaxGLESVersion();
549 
getDpr()550     float getDpr() const { return m_dpr; }
windowWidth()551     int windowWidth() const { return m_windowWidth; }
windowHeight()552     int windowHeight() const { return m_windowHeight; }
getPx()553     float getPx() const { return m_px; }
getPy()554     float getPy() const { return m_py; }
getZrot()555     int getZrot() const { return m_zRot; }
556 
557     bool isFastBlitSupported() const;
558     void disableFastBlitForTesting();
559 
isVulkanInteropSupported()560     bool isVulkanInteropSupported() const { return m_vulkanInteropSupported; }
isVulkanEnabled()561     bool isVulkanEnabled() const { return m_vulkanEnabled; }
562 
563     // Fill GLES usage protobuf
564     void fillGLESUsages(android_studio::EmulatorGLESUsages*);
565 
566     // Saves a screenshot of the previous frame.
567     // nChannels should be 3 (RGB) or 4 (RGBA).
568     // You must provide a pre-allocated buffer of sufficient
569     // size. Returns 0 on success. In the case of failure and if *cPixels != 0
570     // you can call this function again with a buffer of size *cPixels. cPixels
571     // should usually be at at least desiredWidth * desiredHeight * nChannels.
572     //
573     // In practice the buffer should be > desiredWidth *
574     // desiredHeight * nChannels.
575     //
576     // Note: Do not call this function again if it fails and *cPixels == 0
577     //  swiftshader_indirect does not work with 3 channels
578     //
579     // This function supports rectangle snipping by
580     // providing an |rect| parameter. The default value of {{0,0}, {0,0}}
581     // indicates the users wants to snip the entire screen instead of a
582     // partial screen.
583     // - |rect|  represents a rectangle within the screen defined by
584     // desiredWidth and desiredHeight.
585     int getScreenshot(unsigned int nChannels, unsigned int* width, unsigned int* height,
586                       uint8_t* pixels, size_t* cPixels, int displayId, int desiredWidth,
587                       int desiredHeight, int desiredRotation, Rect rect = {{0, 0}, {0, 0}});
588 
589     void onLastColorBufferRef(uint32_t handle);
590     ColorBufferPtr findColorBuffer(HandleType p_colorbuffer);
591     BufferPtr findBuffer(HandleType p_buffer);
592 
593     void registerProcessCleanupCallback(void* key,
594                                         std::function<void()> callback);
595     void unregisterProcessCleanupCallback(void* key);
596 
597     const ProcessResources* getProcessResources(uint64_t puid);
598 
599     int createDisplay(uint32_t *displayId);
600     int createDisplay(uint32_t displayId);
601     int destroyDisplay(uint32_t displayId);
602     int setDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer);
603     int getDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer);
604     int getColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId);
605     int getDisplayPose(uint32_t displayId, int32_t* x, int32_t* y, uint32_t* w,
606                        uint32_t* h);
607     int setDisplayPose(uint32_t displayId, int32_t x, int32_t y, uint32_t w,
608                        uint32_t h, uint32_t dpi = 0);
609     void getCombinedDisplaySize(int* w, int* h);
610     struct DisplayInfo {
611         uint32_t cb;
612         int32_t pos_x;
613         int32_t pos_y;
614         uint32_t width;
615         uint32_t height;
616         uint32_t dpi;
DisplayInfoDisplayInfo617         DisplayInfo()
618             : cb(0), pos_x(0), pos_y(0), width(0), height(0), dpi(0){};
DisplayInfoDisplayInfo619         DisplayInfo(uint32_t cb, int32_t x, int32_t y, uint32_t w, uint32_t h,
620                     uint32_t d)
621             : cb(cb), pos_x(x), pos_y(y), width(w), height(h), dpi(d) {}
622     };
623     // Inline with MultiDisplay::s_invalidIdMultiDisplay
624     static const uint32_t s_invalidIdMultiDisplay = 0xFFFFFFAB;
625     static const uint32_t s_maxNumMultiDisplay = 11;
626 
627     EGLContext getGlobalEGLContext() const;
getLastPostedColorBuffer()628     HandleType getLastPostedColorBuffer() { return m_lastPostedColorBuffer; }
629     void waitForGpu(uint64_t eglsync);
630     void waitForGpuVulkan(uint64_t deviceHandle, uint64_t fenceHandle);
631     void asyncWaitForGpuWithCb(uint64_t eglsync, FenceCompletionCallback cb);
632     void asyncWaitForGpuVulkanWithCb(uint64_t deviceHandle, uint64_t fenceHandle, FenceCompletionCallback cb);
633     void asyncWaitForGpuVulkanQsriWithCb(uint64_t image, FenceCompletionCallback cb);
634     void waitForGpuVulkanQsri(uint64_t image);
635 
636     bool platformImportResource(uint32_t handle, uint32_t info, void* resource);
637     void* platformCreateSharedEglContext(void);
638     bool platformDestroySharedEglContext(void* context);
639 
640     void setGuestManagedColorBufferLifetime(bool guestManaged);
641 
642     std::unique_ptr<BorrowedImageInfo> borrowColorBufferForComposition(uint32_t colorBufferHandle,
643                                                                        bool colorBufferIsTarget);
644     std::unique_ptr<BorrowedImageInfo> borrowColorBufferForDisplay(uint32_t colorBufferHandle);
645 
getHealthMonitor()646     HealthMonitor<>* getHealthMonitor() { return m_healthMonitor.get(); }
647 
getMetricsLogger()648     emugl::MetricsLogger& getMetricsLogger() {
649         return *m_logger;
650     }
651 
652     void logVulkanOutOfMemory(VkResult result, const char* function, int line,
653                               std::optional<uint64_t> allocationSize = std::nullopt);
654 
655     void setVsyncHz(int vsyncHz);
656     void scheduleVsyncTask(VsyncThread::VsyncTask task);
657     void setDisplayConfigs(int configId, int w, int h, int dpiX, int dpiY);
658     void setDisplayActiveConfig(int configId);
659     const int getDisplayConfigsCount();
660     const int getDisplayConfigsParam(int configId, EGLint param);
661     const int getDisplayActiveConfig();
662 
663     bool flushColorBufferFromGl(HandleType colorBufferHandle);
664     bool flushColorBufferFromGlLocked(HandleType colorBufferHandle);
665     bool flushColorBufferFromVk(HandleType colorBufferHandle);
666     bool flushColorBufferFromVkBytes(HandleType colorBufferHandle, const void* bytes, size_t bytesSize);
667     bool invalidateColorBufferForGl(HandleType colorBufferHandle);
668     bool invalidateColorBufferForVk(HandleType colorBufferHandle);
669 
670     const gl::EGLDispatch* getEglDispatch();
671     const gl::GLESv2Dispatch* getGles2Dispatch();
672 
673    private:
674     FrameBuffer(int p_width, int p_height, bool useSubWindow);
675     // Requires the caller to hold the m_colorBufferMapLock until the new handle is inserted into of
676     // the object handle maps.
677     HandleType genHandle_locked();
678 
679     bool removeSubWindow_locked();
680     // Returns the set of ColorBuffers destroyed (for further cleanup)
681     std::vector<HandleType> cleanupProcGLObjects_locked(uint64_t puid,
682                                                         bool forced = false);
683 
684     void markOpened(ColorBufferRef* cbRef);
685     // Returns true if the color buffer was erased.
686     bool closeColorBufferLocked(HandleType p_colorbuffer, bool forced = false);
687     // Returns true if this was the last ref and we need to destroy stuff.
688     bool decColorBufferRefCountLocked(HandleType p_colorbuffer);
689     // Decrease refcount but not destroy the object.
690     // Mainly used in post thread, when we need to destroy the object but cannot in post thread.
691     void decColorBufferRefCountNoDestroy(HandleType p_colorbuffer);
692     // Close all expired color buffers for real.
693     // Treat all delayed color buffers as expired if forced=true
694     void performDelayedColorBufferCloseLocked(bool forced = false);
695     void eraseDelayedCloseColorBufferLocked(HandleType cb, uint64_t ts);
696 
697     AsyncResult postImpl(HandleType p_colorbuffer, Post::CompletionCallback callback,
698                   bool needLockAndBind = true, bool repaint = false);
699     bool postImplSync(HandleType p_colorbuffer, bool needLockAndBind = true, bool repaint = false);
setGuestPostedAFrame()700     void setGuestPostedAFrame() {
701         m_guestPostedAFrame = true;
702         fireEvent({FrameBufferChange::FrameReady, mFrameNumber++});
703     }
704     HandleType createColorBufferWithHandleLocked(int p_width, int p_height, GLenum p_internalFormat,
705                                                  FrameworkFormat p_frameworkFormat,
706                                                  HandleType handle);
707     HandleType createBufferWithHandleLocked(int p_size, HandleType handle, uint32_t memoryProperty);
708 
709     void recomputeLayout();
710     void setDisplayPoseInSkinUI(int totalHeight);
711     void sweepColorBuffersLocked();
712 
713     std::future<void> blockPostWorker(std::future<void> continueSignal);
714 
715    private:
716 
717     static FrameBuffer* s_theFrameBuffer;
718     static HandleType s_nextHandle;
719     int m_x = 0;
720     int m_y = 0;
721     int m_framebufferWidth = 0;
722     int m_framebufferHeight = 0;
723     std::atomic_int m_windowWidth = 0;
724     std::atomic_int m_windowHeight = 0;
725     float m_dpr = 0;
726 
727     bool m_useSubWindow = false;
728 
729     bool m_fpsStats = false;
730     bool m_perfStats = false;
731     int m_statsNumFrames = 0;
732     long long m_statsStartTime = 0;
733 
734     android::base::Thread* m_perfThread;
735     android::base::Lock m_lock;
736     android::base::ReadWriteLock m_contextStructureLock;
737     android::base::Lock m_colorBufferMapLock;
738     uint64_t mFrameNumber;
739     FBNativeWindowType m_nativeWindow = 0;
740     gl::EmulatedEglContextMap m_contexts;
741     gl::EmulatedEglImageMap m_images;
742     gl::EmulatedEglWindowSurfaceMap m_windows;
743     ColorBufferMap m_colorbuffers;
744     BufferMap m_buffers;
745     std::unordered_map<HandleType, HandleType> m_EmulatedEglWindowSurfaceToColorBuffer;
746 
747     // A collection of color buffers that were closed without any usages
748     // (|opened| == false).
749     //
750     // If a buffer reached |refcount| == 0 while not being |opened|, instead of
751     // deleting it we remember the timestamp when this happened. Later, we
752     // check if the buffer stayed unopened long enough and if it did, we delete
753     // it permanently. On the other hand, if the color buffer was used then
754     // we don't care about timestamps anymore.
755     //
756     // Note: this collection is ordered by |ts| field.
757     struct ColorBufferCloseInfo {
758         uint64_t ts;          // when we got the close request.
759         HandleType cbHandle;  // 0 == already closed, do nothing
760     };
761     using ColorBufferDelayedClose = std::vector<ColorBufferCloseInfo>;
762     ColorBufferDelayedClose m_colorBufferDelayedCloseList;
763 
764     EGLNativeWindowType m_subWin = {};
765     HandleType m_lastPostedColorBuffer = 0;
766     float m_zRot = 0;
767     float m_px = 0;
768     float m_py = 0;
769 
770     // Async readback
771     enum class ReadbackCmd {
772         Init = 0,
773         GetPixels = 1,
774         AddRecordDisplay = 2,
775         DelRecordDisplay = 3,
776         Exit = 4,
777     };
778     struct Readback {
779         ReadbackCmd cmd;
780         uint32_t displayId;
781         void* pixelsOut;
782         uint32_t bytes;
783         uint32_t width;
784         uint32_t height;
785     };
786     android::base::WorkerProcessingResult sendReadbackWorkerCmd(
787         const Readback& readback);
788     bool m_guestPostedAFrame = false;
789 
790     struct onPost {
791         Renderer::OnPostCallback cb;
792         void* context;
793         uint32_t displayId;
794         uint32_t width;
795         uint32_t height;
796         unsigned char* img = nullptr;
797         bool readBgra;
~onPostonPost798         ~onPost() {
799             if (img) {
800                 delete[] img;
801                 img = nullptr;
802             }
803         }
804     };
805     std::map<uint32_t, onPost> m_onPost;
806     ReadbackWorker* m_readbackWorker = nullptr;
807     android::base::WorkerThread<Readback> m_readbackThread;
808     std::atomic_bool m_readbackThreadStarted = false;
809 
810     std::string m_graphicsAdapterVendor;
811     std::string m_graphicsAdapterName;
812     std::string m_graphicsApiVersion;
813     std::string m_graphicsApiExtensions;
814     std::string m_graphicsDeviceExtensions;
815 
816     // The host associates color buffers with guest processes for memory
817     // cleanup. Guest processes are identified with a host generated unique ID.
818     // TODO(kaiyili): move all those resources to the ProcessResources struct.
819     ProcOwnedColorBuffers m_procOwnedColorBuffers;
820     ProcOwnedEmulatedEGLImages m_procOwnedEmulatedEglImages;
821     ProcOwnedEmulatedEglContexts m_procOwnedEmulatedEglContexts;
822     ProcOwnedEmulatedEglWindowSurfaces m_procOwnedEmulatedEglWindowSurfaces;
823     ProcOwnedCleanupCallbacks m_procOwnedCleanupCallbacks;
824     std::unordered_map<uint64_t, std::unique_ptr<ProcessResources>> m_procOwnedResources;
825 
826     // Flag set when emulator is shutting down.
827     bool m_shuttingDown = false;
828 
829     // When this feature is enabled, open/close operations from gralloc in guest
830     // will no longer control the reference counting of color buffers on host.
831     // Instead, it will be managed by a file descriptor in the guest kernel. In
832     // case all the native handles in guest are destroyed, the pipe will be
833     // automatically closed by the kernel. We only need to do reference counting
834     // for color buffers attached in window surface.
835     bool m_refCountPipeEnabled = false;
836 
837     // When this feature is enabled, and m_refCountPipeEnabled == false, color
838     // buffer close operations will immediately close the color buffer if host
839     // refcount hits 0. This is for use with guest kernels where the color
840     // buffer is already tied to a file descriptor in the guest kernel.
841     bool m_noDelayCloseColorBufferEnabled = false;
842 
843     std::unique_ptr<PostWorker> m_postWorker = {};
844     std::atomic_bool m_postThreadStarted = false;
845     android::base::WorkerThread<Post> m_postThread;
846     android::base::WorkerProcessingResult postWorkerFunc(Post& post);
847     std::future<void> sendPostWorkerCmd(Post post);
848 
849     bool m_vulkanInteropSupported = false;
850     bool m_vulkanEnabled = false;
851     bool m_guestUsesAngle = false;
852     // Whether the guest manages ColorBuffer lifetime
853     // so we don't need refcounting on the host side.
854     bool m_guestManagedColorBufferLifetime = false;
855 
856     android::base::MessageChannel<HandleType, 1024>
857         mOutstandingColorBufferDestroys;
858 
859     std::unique_ptr<gl::EmulationGl> m_emulationGl;
860     gl::DisplayGl* m_displayGl = nullptr;
861 
862     Compositor* m_compositor = nullptr;
863     bool m_useVulkanComposition = false;
864 
865     vk::VkEmulation* m_emulationVk = nullptr;
866     // The implementation for Vulkan native swapchain. Only initialized when useVulkan is set when
867     // calling FrameBuffer::initialize(). DisplayVk is actually owned by VkEmulation.
868     vk::DisplayVk* m_displayVk = nullptr;
869     VkInstance m_vkInstance = VK_NULL_HANDLE;
870     std::unique_ptr<emugl::RenderDoc> m_renderDoc = nullptr;
871 
872     // TODO(b/233939967): Refactor to create DisplayGl and DisplaySurfaceGl
873     // and remove usage of non-generic DisplayVk.
874     Display* m_display;
875     std::unique_ptr<DisplaySurface> m_displaySurface;
876 
877     // CompositorGl.
878     // TODO: update RenderDoc to be a DisplaySurfaceUser.
879     std::vector<DisplaySurfaceUser*> m_displaySurfaceUsers;
880 
881     // UUIDs of physical devices for Vulkan and GLES, respectively.  In most
882     // cases, this determines whether we can support zero-copy interop.
883     using VkUuid = std::array<uint8_t, VK_UUID_SIZE>;
884     VkUuid m_vulkanUUID{};
885     static_assert(VK_UUID_SIZE == GL_UUID_SIZE_EXT);
886 
887     // Tracks platform EGL contexts that have been handed out to other users,
888     // indexed by underlying native EGL context object.
889     struct PlatformEglContextInfo {
890         EGLContext context;
891         EGLSurface surface;
892     };
893     std::unordered_map<void*, PlatformEglContextInfo> m_platformEglContexts;
894 
895     std::unique_ptr<MetricsLogger> m_logger;
896     std::unique_ptr<HealthMonitor<>> m_healthMonitor;
897 
898     int m_vsyncHz = 60;
899 
900     // Vsync thread.
901     std::unique_ptr<VsyncThread> m_vsyncThread = {};
902 
903     struct DisplayConfig{
904         int w;
905         int h;
906         int dpiX;
907         int dpiY;
DisplayConfigDisplayConfig908         DisplayConfig() {}
DisplayConfigDisplayConfig909         DisplayConfig(int w, int h, int x, int y)
910         : w(w), h(h), dpiX(x), dpiY(y) {}
911     };
912     std::map<int, DisplayConfig> mDisplayConfigs;
913     int mDisplayActiveConfigId = -1;
914 };
915 
916 }  // namespace gfxstream
917 
918 #endif
919