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