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