• 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 #include "gl/EmulationGl.h"
18 #include "host-common/GfxstreamFatalError.h"
19 #include "host-common/logging.h"
20 #include "vulkan/ColorBufferVk.h"
21 #include "vulkan/VkCommonOperations.h"
22 
23 using android::base::ManagedDescriptor;
24 using emugl::ABORT_REASON_OTHER;
25 using emugl::FatalError;
26 
27 namespace gfxstream {
28 namespace {
29 
30 // ColorBufferVk natively supports YUV images. However, ColorBufferGl
31 // needs to emulate YUV support by having an underlying RGBA texture
32 // and adding in additional YUV<->RGBA conversions when needed. The
33 // memory should not be shared between the VK YUV image and the GL RGBA
34 // texture.
shouldAttemptExternalMemorySharing(FrameworkFormat format)35 bool shouldAttemptExternalMemorySharing(FrameworkFormat format) {
36     return format == FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE;
37 }
38 
39 }  // namespace
40 
ColorBuffer(HandleType handle,uint32_t width,uint32_t height,GLenum format,FrameworkFormat frameworkFormat)41 ColorBuffer::ColorBuffer(HandleType handle, uint32_t width, uint32_t height, GLenum format,
42                          FrameworkFormat frameworkFormat)
43     : mHandle(handle),
44       mWidth(width),
45       mHeight(height),
46       mFormat(format),
47       mFrameworkFormat(frameworkFormat) {}
48 
49 /*static*/
create(gl::EmulationGl * emulationGl,vk::VkEmulation * emulationVk,uint32_t width,uint32_t height,GLenum format,FrameworkFormat frameworkFormat,HandleType handle)50 std::shared_ptr<ColorBuffer> ColorBuffer::create(gl::EmulationGl* emulationGl,
51                                                  vk::VkEmulation* emulationVk, uint32_t width,
52                                                  uint32_t height, GLenum format,
53                                                  FrameworkFormat frameworkFormat,
54                                                  HandleType handle) {
55     std::shared_ptr<ColorBuffer> colorBuffer(
56         new ColorBuffer(handle, width, height, format, frameworkFormat));
57 
58     if (emulationGl) {
59         colorBuffer->mColorBufferGl =
60             emulationGl->createColorBuffer(width, height, format, frameworkFormat, handle);
61         if (!colorBuffer->mColorBufferGl) {
62             ERR("Failed to initialize ColorBufferGl.");
63             return nullptr;
64         }
65     }
66 
67     if (emulationVk && emulationVk->live) {
68         const bool vulkanOnly = colorBuffer->mColorBufferGl == nullptr;
69 
70         colorBuffer->mColorBufferVk =
71             vk::ColorBufferVk::create(handle, width, height, format, frameworkFormat, vulkanOnly,
72                                       VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
73         if (!colorBuffer->mColorBufferVk) {
74             if (emulationGl) {
75                 // Historically, ColorBufferVk setup was deferred until the first actual Vulkan
76                 // usage. This allowed ColorBufferVk setup failures to be unintentionally avoided.
77             } else {
78                 ERR("Failed to initialize ColorBufferVk.");
79                 return nullptr;
80             }
81         }
82     }
83 
84     bool b271028352Workaround = emulationGl && strstr(emulationGl->getGlesRenderer().c_str(), "Intel");
85 
86     if (colorBuffer->mColorBufferGl && colorBuffer->mColorBufferVk &&
87         !b271028352Workaround && shouldAttemptExternalMemorySharing(frameworkFormat)) {
88         auto memoryExport = vk::exportColorBufferMemory(handle);
89         if (memoryExport) {
90             if (colorBuffer->mColorBufferGl->importMemory(
91                     std::move(memoryExport->descriptor), memoryExport->size,
92                     memoryExport->dedicatedAllocation, memoryExport->linearTiling)) {
93                 colorBuffer->mGlAndVkAreSharingExternalMemory = true;
94             } else {
95                 ERR("Failed to import memory to ColorBufferGl:%d", handle);
96                 return nullptr;
97             }
98         }
99     }
100 
101     return colorBuffer;
102 }
103 
104 /*static*/
onLoad(gl::EmulationGl * emulationGl,vk::VkEmulation *,android::base::Stream * stream)105 std::shared_ptr<ColorBuffer> ColorBuffer::onLoad(gl::EmulationGl* emulationGl, vk::VkEmulation*,
106                                                  android::base::Stream* stream) {
107     const auto handle = static_cast<HandleType>(stream->getBe32());
108     const auto width = static_cast<uint32_t>(stream->getBe32());
109     const auto height = static_cast<uint32_t>(stream->getBe32());
110     const auto format = static_cast<GLenum>(stream->getBe32());
111     const auto frameworkFormat = static_cast<FrameworkFormat>(stream->getBe32());
112 
113     std::shared_ptr<ColorBuffer> colorBuffer(
114         new ColorBuffer(handle, width, height, format, frameworkFormat));
115 
116     if (emulationGl) {
117         colorBuffer->mColorBufferGl = emulationGl->loadColorBuffer(stream);
118         if (!colorBuffer->mColorBufferGl) {
119             ERR("Failed to load ColorBufferGl.");
120             return nullptr;
121         }
122     }
123 
124     colorBuffer->mNeedRestore = true;
125 
126     return colorBuffer;
127 }
128 
onSave(android::base::Stream * stream)129 void ColorBuffer::onSave(android::base::Stream* stream) {
130     stream->putBe32(getHndl());
131     stream->putBe32(mWidth);
132     stream->putBe32(mHeight);
133     stream->putBe32(static_cast<uint32_t>(mFormat));
134     stream->putBe32(static_cast<uint32_t>(mFrameworkFormat));
135 
136     if (mColorBufferGl) {
137         mColorBufferGl->onSave(stream);
138     }
139 }
140 
restore()141 void ColorBuffer::restore() {
142     if (mColorBufferGl) {
143         mColorBufferGl->restore();
144     }
145 }
146 
readToBytes(int x,int y,int width,int height,GLenum pixelsFormat,GLenum pixelsType,void * outPixels)147 void ColorBuffer::readToBytes(int x, int y, int width, int height, GLenum pixelsFormat,
148                               GLenum pixelsType, void* outPixels) {
149     touch();
150 
151     if (mColorBufferGl) {
152         mColorBufferGl->readPixels(x, y, width, height, pixelsFormat, pixelsType, outPixels);
153         return;
154     }
155     if (mColorBufferVk) {
156         mColorBufferVk->readToBytes(x, y, width, height, outPixels);
157         return;
158     }
159 
160     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
161 }
162 
readToBytesScaled(int pixelsWidth,int pixelsHeight,GLenum pixelsFormat,GLenum pixelsType,int pixelsRotation,Rect rect,void * outPixels)163 void ColorBuffer::readToBytesScaled(int pixelsWidth, int pixelsHeight, GLenum pixelsFormat,
164                                     GLenum pixelsType, int pixelsRotation, Rect rect,
165                                     void* outPixels) {
166     touch();
167 
168     if (mColorBufferGl) {
169         mColorBufferGl->readPixelsScaled(pixelsWidth, pixelsHeight, pixelsFormat, pixelsType,
170                                          pixelsRotation, rect, outPixels);
171         return;
172     }
173 
174     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented.";
175 }
176 
readYuvToBytes(int x,int y,int width,int height,void * outPixels,uint32_t pixelsSize)177 void ColorBuffer::readYuvToBytes(int x, int y, int width, int height, void* outPixels,
178                                  uint32_t pixelsSize) {
179     touch();
180 
181     if (mColorBufferGl) {
182         mColorBufferGl->readPixelsYUVCached(x, y, width, height, outPixels, pixelsSize);
183         return;
184     }
185     if (mColorBufferVk) {
186         mColorBufferVk->readToBytes(x, y, width, height, outPixels);
187         return;
188     }
189 
190     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
191 }
192 
updateFromBytes(int x,int y,int width,int height,FrameworkFormat frameworkFormat,GLenum pixelsFormat,GLenum pixelsType,const void * pixels)193 bool ColorBuffer::updateFromBytes(int x, int y, int width, int height,
194                                   FrameworkFormat frameworkFormat, GLenum pixelsFormat,
195                                   GLenum pixelsType, const void* pixels) {
196     touch();
197 
198     if (mColorBufferGl) {
199         mColorBufferGl->subUpdateFromFrameworkFormat(x, y, width, height, frameworkFormat,
200                                                      pixelsFormat, pixelsType, pixels);
201         return true;
202     }
203     if (mColorBufferVk) {
204         return mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
205     }
206 
207     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
208     return false;
209 }
210 
updateFromBytes(int x,int y,int width,int height,GLenum pixelsFormat,GLenum pixelsType,const void * pixels)211 bool ColorBuffer::updateFromBytes(int x, int y, int width, int height, GLenum pixelsFormat,
212                                   GLenum pixelsType, const void* pixels) {
213     touch();
214 
215     if (mColorBufferGl) {
216         return mColorBufferGl->subUpdate(x, y, width, height, pixelsFormat, pixelsType, pixels);
217     }
218     if (mColorBufferVk) {
219         return mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
220     }
221 
222     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
223     return false;
224 }
225 
updateGlFromBytes(const void * bytes,std::size_t bytesSize)226 bool ColorBuffer::updateGlFromBytes(const void* bytes, std::size_t bytesSize) {
227     if (mColorBufferGl) {
228         touch();
229 
230         return mColorBufferGl->replaceContents(bytes, bytesSize);
231     }
232 
233     return true;
234 }
235 
borrowForComposition(UsedApi api,bool isTarget)236 std::unique_ptr<BorrowedImageInfo> ColorBuffer::borrowForComposition(UsedApi api, bool isTarget) {
237     switch (api) {
238         case UsedApi::kGl: {
239             if (!mColorBufferGl) {
240                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
241             }
242             return mColorBufferGl->getBorrowedImageInfo();
243         }
244         case UsedApi::kVk: {
245             if (!mColorBufferVk) {
246                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
247             }
248             return vk::borrowColorBufferForComposition(getHndl(), isTarget);
249         }
250     }
251     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented";
252     return nullptr;
253 }
254 
borrowForDisplay(UsedApi api)255 std::unique_ptr<BorrowedImageInfo> ColorBuffer::borrowForDisplay(UsedApi api) {
256     switch (api) {
257         case UsedApi::kGl: {
258             if (!mColorBufferGl) {
259                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
260             }
261             return mColorBufferGl->getBorrowedImageInfo();
262         }
263         case UsedApi::kVk: {
264             if (!mColorBufferVk) {
265                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
266             }
267             return vk::borrowColorBufferForDisplay(getHndl());
268         }
269     }
270     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented";
271     return nullptr;
272 }
273 
flushFromGl()274 bool ColorBuffer::flushFromGl() {
275     if (!(mColorBufferGl && mColorBufferVk)) {
276         return true;
277     }
278 
279     if (mGlAndVkAreSharingExternalMemory) {
280         return true;
281     }
282 
283     // ColorBufferGl is currently considered the "main" backing. If this changes,
284     // the "main"  should be updated from the current contents of the GL backing.
285     return true;
286 }
287 
flushFromVk()288 bool ColorBuffer::flushFromVk() {
289     if (!(mColorBufferGl && mColorBufferVk)) {
290         return true;
291     }
292 
293     if (mGlAndVkAreSharingExternalMemory) {
294         return true;
295     }
296 
297     std::vector<uint8_t> contents;
298     if (!vk::readColorBufferToBytes(mHandle, &contents)) {
299         ERR("Failed to get VK contents for ColorBuffer:%d", mHandle);
300         return false;
301     }
302 
303     if (contents.empty()) {
304         return false;
305     }
306 
307     if (!mColorBufferGl->replaceContents(contents.data(), contents.size())) {
308         ERR("Failed to set GL contents for ColorBuffer:%d", mHandle);
309         return false;
310     }
311 
312     return true;
313 }
314 
flushFromVkBytes(const void * bytes,size_t bytesSize)315 bool ColorBuffer::flushFromVkBytes(const void* bytes, size_t bytesSize) {
316     if (!(mColorBufferGl && mColorBufferVk)) {
317         return true;
318     }
319 
320     if (mGlAndVkAreSharingExternalMemory) {
321         return true;
322     }
323 
324     if (mColorBufferGl) {
325         if (!mColorBufferGl->replaceContents(bytes, bytesSize)) {
326             ERR("Failed to update ColorBuffer:%d GL backing from VK bytes.", mHandle);
327             return false;
328         }
329     }
330 
331     return true;
332 }
333 
invalidateForGl()334 bool ColorBuffer::invalidateForGl() {
335     if (!(mColorBufferGl && mColorBufferVk)) {
336         return true;
337     }
338 
339     if (mGlAndVkAreSharingExternalMemory) {
340         return true;
341     }
342 
343     // ColorBufferGl is currently considered the "main" backing. If this changes,
344     // the GL backing should be updated from the "main" backing.
345     return true;
346 }
347 
invalidateForVk()348 bool ColorBuffer::invalidateForVk() {
349     if (!(mColorBufferGl && mColorBufferVk)) {
350         return true;
351     }
352 
353     if (mGlAndVkAreSharingExternalMemory) {
354         return true;
355     }
356 
357     std::size_t contentsSize = 0;
358     if (!mColorBufferGl->readContents(&contentsSize, nullptr)) {
359         ERR("Failed to get GL contents size for ColorBuffer:%d", mHandle);
360         return false;
361     }
362 
363     std::vector<uint8_t> contents(contentsSize, 0);
364 
365     if (!mColorBufferGl->readContents(&contentsSize, contents.data())) {
366         ERR("Failed to get GL contents for ColorBuffer:%d", mHandle);
367         return false;
368     }
369 
370     if (!mColorBufferVk->updateFromBytes(contents)) {
371         ERR("Failed to set VK contents for ColorBuffer:%d", mHandle);
372         return false;
373     }
374 
375     return true;
376 }
377 
glOpBlitFromCurrentReadBuffer()378 bool ColorBuffer::glOpBlitFromCurrentReadBuffer() {
379     if (!mColorBufferGl) {
380         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
381     }
382 
383     touch();
384 
385     return mColorBufferGl->blitFromCurrentReadBuffer();
386 }
387 
glOpBindToTexture()388 bool ColorBuffer::glOpBindToTexture() {
389     if (!mColorBufferGl) {
390         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
391     }
392 
393     touch();
394 
395     return mColorBufferGl->bindToTexture();
396 }
397 
glOpBindToTexture2()398 bool ColorBuffer::glOpBindToTexture2() {
399     if (!mColorBufferGl) {
400         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
401     }
402 
403     return mColorBufferGl->bindToTexture2();
404 }
405 
glOpBindToRenderbuffer()406 bool ColorBuffer::glOpBindToRenderbuffer() {
407     if (!mColorBufferGl) {
408         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
409     }
410 
411     touch();
412 
413     return mColorBufferGl->bindToRenderbuffer();
414 }
415 
glOpGetTexture()416 GLuint ColorBuffer::glOpGetTexture() {
417     if (!mColorBufferGl) {
418         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
419     }
420 
421     touch();
422 
423     return mColorBufferGl->getTexture();
424 }
425 
glOpReadback(unsigned char * img,bool readbackBgra)426 void ColorBuffer::glOpReadback(unsigned char* img, bool readbackBgra) {
427     if (!mColorBufferGl) {
428         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
429     }
430 
431     touch();
432 
433     return mColorBufferGl->readback(img, readbackBgra);
434 }
435 
glOpReadbackAsync(GLuint buffer,bool readbackBgra)436 void ColorBuffer::glOpReadbackAsync(GLuint buffer, bool readbackBgra) {
437     if (!mColorBufferGl) {
438         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
439     }
440 
441     touch();
442 
443     mColorBufferGl->readbackAsync(buffer, readbackBgra);
444 }
445 
glOpImportEglImage(void * image,bool preserveContent)446 bool ColorBuffer::glOpImportEglImage(void* image, bool preserveContent) {
447     if (!mColorBufferGl) {
448         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
449     }
450 
451     return mColorBufferGl->importEglImage(image, preserveContent);
452 }
453 
glOpImportEglNativePixmap(void * pixmap,bool preserveContent)454 bool ColorBuffer::glOpImportEglNativePixmap(void* pixmap, bool preserveContent) {
455     if (!mColorBufferGl) {
456         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
457     }
458 
459     return mColorBufferGl->importEglNativePixmap(pixmap, preserveContent);
460 }
461 
glOpSwapYuvTexturesAndUpdate(GLenum format,GLenum type,FrameworkFormat frameworkFormat,GLuint * textures)462 void ColorBuffer::glOpSwapYuvTexturesAndUpdate(GLenum format, GLenum type,
463                                                FrameworkFormat frameworkFormat, GLuint* textures) {
464     if (!mColorBufferGl) {
465         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
466     }
467 
468     mColorBufferGl->swapYUVTextures(frameworkFormat, textures);
469 
470     // This makes ColorBufferGl regenerate the RGBA texture using
471     // YUVConverter::drawConvert() with the updated YUV textures.
472     mColorBufferGl->subUpdate(0, 0, mWidth, mHeight, format, type, nullptr);
473 
474     flushFromGl();
475 }
476 
glOpReadContents(size_t * outNumBytes,void * outContents)477 bool ColorBuffer::glOpReadContents(size_t* outNumBytes, void* outContents) {
478     if (!mColorBufferGl) {
479         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
480     }
481 
482     return mColorBufferGl->readContents(outNumBytes, outContents);
483 }
484 
glOpIsFastBlitSupported() const485 bool ColorBuffer::glOpIsFastBlitSupported() const {
486     if (!mColorBufferGl) {
487         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
488     }
489 
490     return mColorBufferGl->isFastBlitSupported();
491 }
492 
glOpPostLayer(const ComposeLayer & l,int frameWidth,int frameHeight)493 void ColorBuffer::glOpPostLayer(const ComposeLayer& l, int frameWidth, int frameHeight) {
494     if (!mColorBufferGl) {
495         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
496     }
497 
498     mColorBufferGl->postLayer(l, frameWidth, frameHeight);
499 }
500 
glOpPostViewportScaledWithOverlay(float rotation,float dx,float dy)501 void ColorBuffer::glOpPostViewportScaledWithOverlay(float rotation, float dx, float dy) {
502     if (!mColorBufferGl) {
503         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
504     }
505 
506     mColorBufferGl->postViewportScaledWithOverlay(rotation, dx, dy);
507 }
508 
509 }  // namespace gfxstream
510