• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "ColorBuffer.h"
16 
17 #if GFXSTREAM_ENABLE_HOST_GLES
18 #include "gl/EmulationGl.h"
19 #endif
20 
21 #include "host-common/GfxstreamFatalError.h"
22 #include "host-common/logging.h"
23 #include "vulkan/ColorBufferVk.h"
24 #include "vulkan/VkCommonOperations.h"
25 #include "FrameBuffer.h"
26 
27 using emugl::ABORT_REASON_OTHER;
28 using emugl::FatalError;
29 
30 namespace gfxstream {
31 namespace {
32 
33 // ColorBufferVk natively supports YUV images. However, ColorBufferGl
34 // needs to emulate YUV support by having an underlying RGBA texture
35 // and adding in additional YUV<->RGBA conversions when needed. The
36 // memory should not be shared between the VK YUV image and the GL RGBA
37 // texture.
shouldAttemptExternalMemorySharing(FrameworkFormat format)38 bool shouldAttemptExternalMemorySharing(FrameworkFormat format) {
39     return format == FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE;
40 }
41 
42 }  // namespace
43 
ColorBuffer(HandleType handle,uint32_t width,uint32_t height,GLenum format,FrameworkFormat frameworkFormat)44 ColorBuffer::ColorBuffer(HandleType handle, uint32_t width, uint32_t height, GLenum format,
45                          FrameworkFormat frameworkFormat)
46     : mHandle(handle),
47       mWidth(width),
48       mHeight(height),
49       mFormat(format),
50       mFrameworkFormat(frameworkFormat) {}
51 
52 /*static*/
create(gl::EmulationGl * emulationGl,vk::VkEmulation * emulationVk,uint32_t width,uint32_t height,GLenum format,FrameworkFormat frameworkFormat,HandleType handle,android::base::Stream * stream,bool linear)53 std::shared_ptr<ColorBuffer> ColorBuffer::create(gl::EmulationGl* emulationGl,
54                                                  vk::VkEmulation* emulationVk, uint32_t width,
55                                                  uint32_t height, GLenum format,
56                                                  FrameworkFormat frameworkFormat, HandleType handle,
57                                                  android::base::Stream* stream, bool linear) {
58     std::shared_ptr<ColorBuffer> colorBuffer(
59         new ColorBuffer(handle, width, height, format, frameworkFormat));
60 
61     if (stream) {
62         // When vk snapshot enabled, mNeedRestore will be touched and set to false immediately.
63         colorBuffer->mNeedRestore = true;
64     }
65 #if GFXSTREAM_ENABLE_HOST_GLES
66     if (emulationGl) {
67         if (stream) {
68             colorBuffer->mColorBufferGl = emulationGl->loadColorBuffer(stream);
69             assert(width == colorBuffer->mColorBufferGl->getWidth());
70             assert(height == colorBuffer->mColorBufferGl->getHeight());
71             assert(frameworkFormat == colorBuffer->mColorBufferGl->getFrameworkFormat());
72         } else {
73             colorBuffer->mColorBufferGl =
74                 emulationGl->createColorBuffer(width, height, format, frameworkFormat, handle);
75         }
76         if (!colorBuffer->mColorBufferGl) {
77             ERR("Failed to initialize ColorBufferGl.");
78             return nullptr;
79         }
80     }
81 #endif
82 
83     if (emulationVk) {
84         const bool vulkanOnly = colorBuffer->mColorBufferGl == nullptr;
85         uint32_t memoryProperty = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
86         if (vulkanOnly && linear) {
87             memoryProperty |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
88         }
89         colorBuffer->mColorBufferVk =
90             vk::ColorBufferVk::create(*emulationVk, handle, width, height, format, frameworkFormat,
91                                       vulkanOnly, memoryProperty, stream);
92         if (!colorBuffer->mColorBufferVk) {
93             if (emulationGl) {
94                 // Historically, ColorBufferVk setup was deferred until the first actual Vulkan
95                 // usage. This allowed ColorBufferVk setup failures to be unintentionally avoided.
96             } else {
97                 ERR("Failed to initialize ColorBufferVk.");
98                 return nullptr;
99             }
100         }
101     }
102 
103 #if GFXSTREAM_ENABLE_HOST_GLES
104     bool vkSnapshotEnabled = emulationVk && emulationVk->getFeatures().VulkanSnapshots.enabled;
105 
106     if ((!stream || vkSnapshotEnabled) && colorBuffer->mColorBufferGl && colorBuffer->mColorBufferVk &&
107         shouldAttemptExternalMemorySharing(frameworkFormat)) {
108         colorBuffer->touch();
109         auto memoryExport = emulationVk->exportColorBufferMemory(handle);
110         if (memoryExport) {
111             if (colorBuffer->mColorBufferGl->importMemory(
112 #ifdef _WIN32
113                     ManagedDescriptor(static_cast<DescriptorType>(
114                         reinterpret_cast<void*>(memoryExport->handleInfo.handle))),
115 #else
116                     ManagedDescriptor(static_cast<DescriptorType>(memoryExport->handleInfo.handle)),
117 #endif
118                     memoryExport->size, memoryExport->dedicatedAllocation,
119                     memoryExport->linearTiling)) {
120                 colorBuffer->mGlAndVkAreSharingExternalMemory = true;
121             } else {
122                 ERR("Failed to import memory to ColorBufferGl:%d", handle);
123             }
124         }
125     }
126 #endif
127 
128     return colorBuffer;
129 }
130 
131 /*static*/
onLoad(gl::EmulationGl * emulationGl,vk::VkEmulation * emulationVk,android::base::Stream * stream)132 std::shared_ptr<ColorBuffer> ColorBuffer::onLoad(gl::EmulationGl* emulationGl,
133                                                  vk::VkEmulation* emulationVk,
134                                                  android::base::Stream* stream) {
135     const auto handle = static_cast<HandleType>(stream->getBe32());
136     const auto width = static_cast<uint32_t>(stream->getBe32());
137     const auto height = static_cast<uint32_t>(stream->getBe32());
138     const auto format = static_cast<GLenum>(stream->getBe32());
139     const auto frameworkFormat = static_cast<FrameworkFormat>(stream->getBe32());
140 
141     std::shared_ptr<ColorBuffer> colorBuffer = ColorBuffer::create(
142         emulationGl, emulationVk, width, height, format, frameworkFormat, handle, stream);
143 
144     return colorBuffer;
145 }
146 
onSave(android::base::Stream * stream)147 void ColorBuffer::onSave(android::base::Stream* stream) {
148     stream->putBe32(getHndl());
149     stream->putBe32(mWidth);
150     stream->putBe32(mHeight);
151     stream->putBe32(static_cast<uint32_t>(mFormat));
152     stream->putBe32(static_cast<uint32_t>(mFrameworkFormat));
153 
154 #if GFXSTREAM_ENABLE_HOST_GLES
155     if (mColorBufferGl) {
156         mColorBufferGl->onSave(stream);
157     }
158 #endif
159     if (mColorBufferVk) {
160         mColorBufferVk->onSave(stream);
161     }
162 }
163 
restore()164 void ColorBuffer::restore() {
165 #if GFXSTREAM_ENABLE_HOST_GLES
166     if (mColorBufferGl) {
167         mColorBufferGl->restore();
168     }
169 #endif
170 }
171 
readToBytes(int x,int y,int width,int height,GLenum pixelsFormat,GLenum pixelsType,void * outPixels,uint64_t outPixelsSize)172 void ColorBuffer::readToBytes(int x, int y, int width, int height, GLenum pixelsFormat,
173                               GLenum pixelsType, void* outPixels, uint64_t outPixelsSize) {
174     touch();
175 
176 #if GFXSTREAM_ENABLE_HOST_GLES
177     if (mColorBufferGl) {
178         mColorBufferGl->readPixels(x, y, width, height, pixelsFormat, pixelsType, outPixels);
179         return;
180     }
181 #endif
182 
183     if (mColorBufferVk) {
184         mColorBufferVk->readToBytes(x, y, width, height, outPixels, outPixelsSize);
185         return;
186     }
187 
188     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
189 }
190 
readToBytesScaled(int pixelsWidth,int pixelsHeight,GLenum pixelsFormat,GLenum pixelsType,int pixelsRotation,Rect rect,void * outPixels)191 void ColorBuffer::readToBytesScaled(int pixelsWidth, int pixelsHeight, GLenum pixelsFormat,
192                                     GLenum pixelsType, int pixelsRotation, Rect rect,
193                                     void* outPixels) {
194     touch();
195 
196 #if GFXSTREAM_ENABLE_HOST_GLES
197     if (mColorBufferGl) {
198         mColorBufferGl->readPixelsScaled(pixelsWidth, pixelsHeight, pixelsFormat, pixelsType,
199                                          pixelsRotation, rect, outPixels);
200         return;
201     }
202 #endif
203 
204     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented.";
205 }
206 
readYuvToBytes(int x,int y,int width,int height,void * outPixels,uint32_t outPixelsSize)207 void ColorBuffer::readYuvToBytes(int x, int y, int width, int height, void* outPixels,
208                                  uint32_t outPixelsSize) {
209     touch();
210 
211 #if GFXSTREAM_ENABLE_HOST_GLES
212     if (mColorBufferGl) {
213         mColorBufferGl->readPixelsYUVCached(x, y, width, height, outPixels, outPixelsSize);
214         return;
215     }
216 #endif
217 
218     if (mColorBufferVk) {
219         mColorBufferVk->readToBytes(x, y, width, height, outPixels, outPixelsSize);
220         return;
221     }
222 
223     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
224 }
225 
updateFromBytes(int x,int y,int width,int height,FrameworkFormat frameworkFormat,GLenum pixelsFormat,GLenum pixelsType,const void * pixels,void * metadata)226 bool ColorBuffer::updateFromBytes(int x, int y, int width, int height,
227                                   FrameworkFormat frameworkFormat, GLenum pixelsFormat,
228                                   GLenum pixelsType, const void* pixels, void* metadata) {
229     touch();
230 
231 #if GFXSTREAM_ENABLE_HOST_GLES
232     if (mColorBufferGl) {
233         mColorBufferGl->subUpdateFromFrameworkFormat(x, y, width, height, frameworkFormat,
234                                                      pixelsFormat, pixelsType, pixels, metadata);
235         flushFromGl();
236         return true;
237     }
238 #endif
239 
240     if (mColorBufferVk) {
241         bool success = mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
242         if (!success) return success;
243         flushFromVk();
244         return true;
245     }
246 
247     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
248     return false;
249 }
250 
updateFromBytes(int x,int y,int width,int height,GLenum pixelsFormat,GLenum pixelsType,const void * pixels)251 bool ColorBuffer::updateFromBytes(int x, int y, int width, int height, GLenum pixelsFormat,
252                                   GLenum pixelsType, const void* pixels) {
253     touch();
254 
255 #if GFXSTREAM_ENABLE_HOST_GLES
256     if (mColorBufferGl) {
257         bool res = mColorBufferGl->subUpdate(x, y, width, height, pixelsFormat, pixelsType, pixels);
258         if (res) {
259             flushFromGl();
260         }
261         return res;
262     }
263 #endif
264 
265     if (mColorBufferVk) {
266         return mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
267     }
268 
269     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
270     return false;
271 }
272 
updateGlFromBytes(const void * bytes,std::size_t bytesSize)273 bool ColorBuffer::updateGlFromBytes(const void* bytes, std::size_t bytesSize) {
274 #if GFXSTREAM_ENABLE_HOST_GLES
275     if (mColorBufferGl) {
276         touch();
277 
278         return mColorBufferGl->replaceContents(bytes, bytesSize);
279     }
280 #endif
281 
282     return true;
283 }
284 
borrowForComposition(UsedApi api,bool isTarget)285 std::unique_ptr<BorrowedImageInfo> ColorBuffer::borrowForComposition(UsedApi api, bool isTarget) {
286     switch (api) {
287         case UsedApi::kGl: {
288 #if GFXSTREAM_ENABLE_HOST_GLES
289             if (!mColorBufferGl) {
290                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
291             }
292             return mColorBufferGl->getBorrowedImageInfo();
293 #endif
294         }
295         case UsedApi::kVk: {
296             if (!mColorBufferVk) {
297                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
298             }
299             return mColorBufferVk->borrowForComposition(isTarget);
300         }
301     }
302     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented";
303     return nullptr;
304 }
305 
borrowForDisplay(UsedApi api)306 std::unique_ptr<BorrowedImageInfo> ColorBuffer::borrowForDisplay(UsedApi api) {
307     switch (api) {
308         case UsedApi::kGl: {
309 #if GFXSTREAM_ENABLE_HOST_GLES
310             if (!mColorBufferGl) {
311                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
312             }
313             return mColorBufferGl->getBorrowedImageInfo();
314 #endif
315         }
316         case UsedApi::kVk: {
317             if (!mColorBufferVk) {
318                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
319             }
320             return mColorBufferVk->borrowForDisplay();
321         }
322     }
323     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented";
324     return nullptr;
325 }
326 
flushFromGl()327 bool ColorBuffer::flushFromGl() {
328     if (!(mColorBufferGl && mColorBufferVk)) {
329         return true;
330     }
331 
332     if (mGlAndVkAreSharingExternalMemory) {
333         return true;
334     }
335 
336     // ColorBufferGl is currently considered the "main" backing. If this changes,
337     // the "main"  should be updated from the current contents of the GL backing.
338     mGlTexDirty = true;
339     return true;
340 }
341 
flushFromVk()342 bool ColorBuffer::flushFromVk() {
343     if (!(mColorBufferGl && mColorBufferVk)) {
344         return true;
345     }
346 
347     if (mGlAndVkAreSharingExternalMemory) {
348         return true;
349     }
350     std::vector<uint8_t> contents;
351     if (!mColorBufferVk->readToBytes(&contents)) {
352         ERR("Failed to get VK contents for ColorBuffer:%d", mHandle);
353         return false;
354     }
355 
356     if (contents.empty()) {
357         return false;
358     }
359 
360 #if GFXSTREAM_ENABLE_HOST_GLES
361     if (!mColorBufferGl->replaceContents(contents.data(), contents.size())) {
362         ERR("Failed to set GL contents for ColorBuffer:%d", mHandle);
363         return false;
364     }
365 #endif
366     mGlTexDirty = false;
367     return true;
368 }
369 
flushFromVkBytes(const void * bytes,size_t bytesSize)370 bool ColorBuffer::flushFromVkBytes(const void* bytes, size_t bytesSize) {
371     if (!(mColorBufferGl && mColorBufferVk)) {
372         return true;
373     }
374 
375     if (mGlAndVkAreSharingExternalMemory) {
376         return true;
377     }
378 
379 #if GFXSTREAM_ENABLE_HOST_GLES
380     if (mColorBufferGl) {
381         if (!mColorBufferGl->replaceContents(bytes, bytesSize)) {
382             ERR("Failed to update ColorBuffer:%d GL backing from VK bytes.", mHandle);
383             return false;
384         }
385     }
386 #endif
387     mGlTexDirty = false;
388     return true;
389 }
390 
invalidateForGl()391 bool ColorBuffer::invalidateForGl() {
392     if (!(mColorBufferGl && mColorBufferVk)) {
393         return true;
394     }
395 
396     if (mGlAndVkAreSharingExternalMemory) {
397         return true;
398     }
399 
400     // ColorBufferGl is currently considered the "main" backing. If this changes,
401     // the GL backing should be updated from the "main" backing.
402     return true;
403 }
404 
invalidateForVk()405 bool ColorBuffer::invalidateForVk() {
406     if (!(mColorBufferGl && mColorBufferVk)) {
407         return true;
408     }
409 
410     if (mGlAndVkAreSharingExternalMemory) {
411         return true;
412     }
413 
414     if (!mGlTexDirty) {
415         return true;
416     }
417 
418 #if GFXSTREAM_ENABLE_HOST_GLES
419     std::size_t contentsSize = 0;
420     if (!mColorBufferGl->readContents(&contentsSize, nullptr)) {
421         ERR("Failed to get GL contents size for ColorBuffer:%d", mHandle);
422         return false;
423     }
424 
425     std::vector<uint8_t> contents(contentsSize, 0);
426 
427     if (!mColorBufferGl->readContents(&contentsSize, contents.data())) {
428         ERR("Failed to get GL contents for ColorBuffer:%d", mHandle);
429         return false;
430     }
431 
432     if (!mColorBufferVk->updateFromBytes(contents)) {
433         ERR("Failed to set VK contents for ColorBuffer:%d", mHandle);
434         return false;
435     }
436 #endif
437     mGlTexDirty = false;
438     return true;
439 }
440 
exportBlob()441 std::optional<BlobDescriptorInfo> ColorBuffer::exportBlob() {
442     if (!mColorBufferVk) {
443         return std::nullopt;
444     }
445 
446     return mColorBufferVk->exportBlob();
447 }
448 
449 #if GFXSTREAM_ENABLE_HOST_GLES
glOpBlitFromCurrentReadBuffer()450 bool ColorBuffer::glOpBlitFromCurrentReadBuffer() {
451     if (!mColorBufferGl) {
452         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
453     }
454 
455     touch();
456 
457     return mColorBufferGl->blitFromCurrentReadBuffer();
458 }
459 
glOpBindToTexture()460 bool ColorBuffer::glOpBindToTexture() {
461     if (!mColorBufferGl) {
462         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
463     }
464 
465     touch();
466 
467     return mColorBufferGl->bindToTexture();
468 }
469 
glOpBindToTexture2()470 bool ColorBuffer::glOpBindToTexture2() {
471     if (!mColorBufferGl) {
472         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
473     }
474 
475     return mColorBufferGl->bindToTexture2();
476 }
477 
glOpBindToRenderbuffer()478 bool ColorBuffer::glOpBindToRenderbuffer() {
479     if (!mColorBufferGl) {
480         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
481     }
482 
483     touch();
484 
485     return mColorBufferGl->bindToRenderbuffer();
486 }
487 
glOpGetTexture()488 GLuint ColorBuffer::glOpGetTexture() {
489     if (!mColorBufferGl) {
490         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
491     }
492 
493     touch();
494 
495     return mColorBufferGl->getTexture();
496 }
497 
glOpReadback(unsigned char * img,bool readbackBgra)498 void ColorBuffer::glOpReadback(unsigned char* img, bool readbackBgra) {
499     if (!mColorBufferGl) {
500         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
501     }
502 
503     touch();
504 
505     return mColorBufferGl->readback(img, readbackBgra);
506 }
507 
glOpReadbackAsync(GLuint buffer,bool readbackBgra)508 void ColorBuffer::glOpReadbackAsync(GLuint buffer, bool readbackBgra) {
509     if (!mColorBufferGl) {
510         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
511     }
512 
513     touch();
514 
515     mColorBufferGl->readbackAsync(buffer, readbackBgra);
516 }
517 
glOpImportEglNativePixmap(void * pixmap,bool preserveContent)518 bool ColorBuffer::glOpImportEglNativePixmap(void* pixmap, bool preserveContent) {
519     if (!mColorBufferGl) {
520         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
521     }
522 
523     return mColorBufferGl->importEglNativePixmap(pixmap, preserveContent);
524 }
525 
glOpSwapYuvTexturesAndUpdate(GLenum format,GLenum type,FrameworkFormat frameworkFormat,GLuint * textures)526 void ColorBuffer::glOpSwapYuvTexturesAndUpdate(GLenum format, GLenum type,
527                                                FrameworkFormat frameworkFormat, GLuint* textures) {
528     if (!mColorBufferGl) {
529         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
530     }
531 
532     mColorBufferGl->swapYUVTextures(frameworkFormat, textures);
533 
534     // This makes ColorBufferGl regenerate the RGBA texture using
535     // YUVConverter::drawConvert() with the updated YUV textures.
536     mColorBufferGl->subUpdate(0, 0, mWidth, mHeight, format, type, nullptr);
537 
538     flushFromGl();
539 }
540 
glOpReadContents(size_t * outNumBytes,void * outContents)541 bool ColorBuffer::glOpReadContents(size_t* outNumBytes, void* outContents) {
542     if (!mColorBufferGl) {
543         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
544     }
545 
546     return mColorBufferGl->readContents(outNumBytes, outContents);
547 }
548 
glOpIsFastBlitSupported() const549 bool ColorBuffer::glOpIsFastBlitSupported() const {
550     if (!mColorBufferGl) {
551         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
552     }
553 
554     return mColorBufferGl->isFastBlitSupported();
555 }
556 
glOpPostLayer(const ComposeLayer & l,int frameWidth,int frameHeight)557 void ColorBuffer::glOpPostLayer(const ComposeLayer& l, int frameWidth, int frameHeight) {
558     if (!mColorBufferGl) {
559         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
560     }
561 
562     mColorBufferGl->postLayer(l, frameWidth, frameHeight);
563 }
564 
glOpPostViewportScaledWithOverlay(float rotation,float dx,float dy)565 void ColorBuffer::glOpPostViewportScaledWithOverlay(float rotation, float dx, float dy) {
566     if (!mColorBufferGl) {
567         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
568     }
569 
570     mColorBufferGl->postViewportScaledWithOverlay(rotation, dx, dy);
571 }
572 #endif
573 
574 }  // namespace gfxstream
575