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