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 android::base::ManagedDescriptor;
28 using emugl::ABORT_REASON_OTHER;
29 using emugl::FatalError;
30
31 namespace gfxstream {
32 namespace {
33
34 // ColorBufferVk natively supports YUV images. However, ColorBufferGl
35 // needs to emulate YUV support by having an underlying RGBA texture
36 // and adding in additional YUV<->RGBA conversions when needed. The
37 // memory should not be shared between the VK YUV image and the GL RGBA
38 // texture.
shouldAttemptExternalMemorySharing(FrameworkFormat format)39 bool shouldAttemptExternalMemorySharing(FrameworkFormat format) {
40 return format == FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE;
41 }
42
43 } // namespace
44
ColorBuffer(HandleType handle,uint32_t width,uint32_t height,GLenum format,FrameworkFormat frameworkFormat)45 ColorBuffer::ColorBuffer(HandleType handle, uint32_t width, uint32_t height, GLenum format,
46 FrameworkFormat frameworkFormat)
47 : mHandle(handle),
48 mWidth(width),
49 mHeight(height),
50 mFormat(format),
51 mFrameworkFormat(frameworkFormat) {}
52
53 /*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)54 std::shared_ptr<ColorBuffer> ColorBuffer::create(gl::EmulationGl* emulationGl,
55 vk::VkEmulation* emulationVk, uint32_t width,
56 uint32_t height, GLenum format,
57 FrameworkFormat frameworkFormat, HandleType handle,
58 android::base::Stream* stream, bool linear) {
59 std::shared_ptr<ColorBuffer> colorBuffer(
60 new ColorBuffer(handle, width, height, format, frameworkFormat));
61
62 if (stream) {
63 // When vk snapshot enabled, mNeedRestore will be touched and set to false immediately.
64 colorBuffer->mNeedRestore = true;
65 }
66 #if GFXSTREAM_ENABLE_HOST_GLES
67 if (emulationGl) {
68 if (stream) {
69 colorBuffer->mColorBufferGl = emulationGl->loadColorBuffer(stream);
70 assert(width == colorBuffer->mColorBufferGl->getWidth());
71 assert(height == colorBuffer->mColorBufferGl->getHeight());
72 assert(frameworkFormat == colorBuffer->mColorBufferGl->getFrameworkFormat());
73 } else {
74 colorBuffer->mColorBufferGl =
75 emulationGl->createColorBuffer(width, height, format, frameworkFormat, handle);
76 }
77 if (!colorBuffer->mColorBufferGl) {
78 ERR("Failed to initialize ColorBufferGl.");
79 return nullptr;
80 }
81 }
82 #endif
83
84 if (emulationVk && emulationVk->live) {
85 const bool vulkanOnly = colorBuffer->mColorBufferGl == nullptr;
86 uint32_t memoryProperty = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
87 if (vulkanOnly && linear) {
88 memoryProperty |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
89 }
90 colorBuffer->mColorBufferVk = vk::ColorBufferVk::create(
91 handle, width, height, format, frameworkFormat, 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 b271028352Workaround = emulationGl && strstr(emulationGl->getGlesRenderer().c_str(), "Intel");
105 bool vkSnapshotEnabled = emulationVk && emulationVk->features.VulkanSnapshots.enabled;
106
107 if ((!stream || vkSnapshotEnabled) && colorBuffer->mColorBufferGl && colorBuffer->mColorBufferVk &&
108 !b271028352Workaround && shouldAttemptExternalMemorySharing(frameworkFormat)) {
109 colorBuffer->touch();
110 auto memoryExport = vk::exportColorBufferMemory(handle);
111 if (memoryExport) {
112 if (colorBuffer->mColorBufferGl->importMemory(
113 std::move(memoryExport->descriptor), memoryExport->size,
114 memoryExport->dedicatedAllocation, memoryExport->linearTiling)) {
115 colorBuffer->mGlAndVkAreSharingExternalMemory = true;
116 } else {
117 ERR("Failed to import memory to ColorBufferGl:%d", handle);
118 }
119 }
120 }
121 #endif
122
123 return colorBuffer;
124 }
125
126 /*static*/
onLoad(gl::EmulationGl * emulationGl,vk::VkEmulation * emulationVk,android::base::Stream * stream)127 std::shared_ptr<ColorBuffer> ColorBuffer::onLoad(gl::EmulationGl* emulationGl,
128 vk::VkEmulation* emulationVk,
129 android::base::Stream* stream) {
130 const auto handle = static_cast<HandleType>(stream->getBe32());
131 const auto width = static_cast<uint32_t>(stream->getBe32());
132 const auto height = static_cast<uint32_t>(stream->getBe32());
133 const auto format = static_cast<GLenum>(stream->getBe32());
134 const auto frameworkFormat = static_cast<FrameworkFormat>(stream->getBe32());
135
136 std::shared_ptr<ColorBuffer> colorBuffer = ColorBuffer::create(
137 emulationGl, emulationVk, width, height, format, frameworkFormat, handle, stream);
138
139 return colorBuffer;
140 }
141
onSave(android::base::Stream * stream)142 void ColorBuffer::onSave(android::base::Stream* stream) {
143 stream->putBe32(getHndl());
144 stream->putBe32(mWidth);
145 stream->putBe32(mHeight);
146 stream->putBe32(static_cast<uint32_t>(mFormat));
147 stream->putBe32(static_cast<uint32_t>(mFrameworkFormat));
148
149 #if GFXSTREAM_ENABLE_HOST_GLES
150 if (mColorBufferGl) {
151 mColorBufferGl->onSave(stream);
152 }
153 #endif
154 if (mColorBufferVk) {
155 mColorBufferVk->onSave(stream);
156 }
157 }
158
restore()159 void ColorBuffer::restore() {
160 #if GFXSTREAM_ENABLE_HOST_GLES
161 if (mColorBufferGl) {
162 mColorBufferGl->restore();
163 }
164 #endif
165 }
166
readToBytes(int x,int y,int width,int height,GLenum pixelsFormat,GLenum pixelsType,void * outPixels,uint64_t outPixelsSize)167 void ColorBuffer::readToBytes(int x, int y, int width, int height, GLenum pixelsFormat,
168 GLenum pixelsType, void* outPixels, uint64_t outPixelsSize) {
169 touch();
170
171 #if GFXSTREAM_ENABLE_HOST_GLES
172 if (mColorBufferGl) {
173 mColorBufferGl->readPixels(x, y, width, height, pixelsFormat, pixelsType, outPixels);
174 return;
175 }
176 #endif
177
178 if (mColorBufferVk) {
179 mColorBufferVk->readToBytes(x, y, width, height, outPixels, outPixelsSize);
180 return;
181 }
182
183 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
184 }
185
readToBytesScaled(int pixelsWidth,int pixelsHeight,GLenum pixelsFormat,GLenum pixelsType,int pixelsRotation,Rect rect,void * outPixels)186 void ColorBuffer::readToBytesScaled(int pixelsWidth, int pixelsHeight, GLenum pixelsFormat,
187 GLenum pixelsType, int pixelsRotation, Rect rect,
188 void* outPixels) {
189 touch();
190
191 #if GFXSTREAM_ENABLE_HOST_GLES
192 if (mColorBufferGl) {
193 mColorBufferGl->readPixelsScaled(pixelsWidth, pixelsHeight, pixelsFormat, pixelsType,
194 pixelsRotation, rect, outPixels);
195 return;
196 }
197 #endif
198
199 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented.";
200 }
201
readYuvToBytes(int x,int y,int width,int height,void * outPixels,uint32_t outPixelsSize)202 void ColorBuffer::readYuvToBytes(int x, int y, int width, int height, void* outPixels,
203 uint32_t outPixelsSize) {
204 touch();
205
206 #if GFXSTREAM_ENABLE_HOST_GLES
207 if (mColorBufferGl) {
208 mColorBufferGl->readPixelsYUVCached(x, y, width, height, outPixels, outPixelsSize);
209 return;
210 }
211 #endif
212
213 if (mColorBufferVk) {
214 mColorBufferVk->readToBytes(x, y, width, height, outPixels, outPixelsSize);
215 return;
216 }
217
218 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
219 }
220
updateFromBytes(int x,int y,int width,int height,FrameworkFormat frameworkFormat,GLenum pixelsFormat,GLenum pixelsType,const void * pixels,void * metadata)221 bool ColorBuffer::updateFromBytes(int x, int y, int width, int height,
222 FrameworkFormat frameworkFormat, GLenum pixelsFormat,
223 GLenum pixelsType, const void* pixels, void* metadata) {
224 touch();
225
226 #if GFXSTREAM_ENABLE_HOST_GLES
227 if (mColorBufferGl) {
228 mColorBufferGl->subUpdateFromFrameworkFormat(x, y, width, height, frameworkFormat,
229 pixelsFormat, pixelsType, pixels, metadata);
230 flushFromGl();
231 return true;
232 }
233 #endif
234
235 if (mColorBufferVk) {
236 bool success = mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
237 if (!success) return success;
238 flushFromVk();
239 return true;
240 }
241
242 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
243 return false;
244 }
245
updateFromBytes(int x,int y,int width,int height,GLenum pixelsFormat,GLenum pixelsType,const void * pixels)246 bool ColorBuffer::updateFromBytes(int x, int y, int width, int height, GLenum pixelsFormat,
247 GLenum pixelsType, const void* pixels) {
248 touch();
249
250 #if GFXSTREAM_ENABLE_HOST_GLES
251 if (mColorBufferGl) {
252 bool res = mColorBufferGl->subUpdate(x, y, width, height, pixelsFormat, pixelsType, pixels);
253 if (res) {
254 flushFromGl();
255 }
256 return res;
257 }
258 #endif
259
260 if (mColorBufferVk) {
261 return mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
262 }
263
264 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
265 return false;
266 }
267
updateGlFromBytes(const void * bytes,std::size_t bytesSize)268 bool ColorBuffer::updateGlFromBytes(const void* bytes, std::size_t bytesSize) {
269 #if GFXSTREAM_ENABLE_HOST_GLES
270 if (mColorBufferGl) {
271 touch();
272
273 return mColorBufferGl->replaceContents(bytes, bytesSize);
274 }
275 #endif
276
277 return true;
278 }
279
borrowForComposition(UsedApi api,bool isTarget)280 std::unique_ptr<BorrowedImageInfo> ColorBuffer::borrowForComposition(UsedApi api, bool isTarget) {
281 switch (api) {
282 case UsedApi::kGl: {
283 #if GFXSTREAM_ENABLE_HOST_GLES
284 if (!mColorBufferGl) {
285 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
286 }
287 return mColorBufferGl->getBorrowedImageInfo();
288 #endif
289 }
290 case UsedApi::kVk: {
291 if (!mColorBufferVk) {
292 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
293 }
294 return vk::borrowColorBufferForComposition(getHndl(), isTarget);
295 }
296 }
297 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented";
298 return nullptr;
299 }
300
borrowForDisplay(UsedApi api)301 std::unique_ptr<BorrowedImageInfo> ColorBuffer::borrowForDisplay(UsedApi api) {
302 switch (api) {
303 case UsedApi::kGl: {
304 #if GFXSTREAM_ENABLE_HOST_GLES
305 if (!mColorBufferGl) {
306 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
307 }
308 return mColorBufferGl->getBorrowedImageInfo();
309 #endif
310 }
311 case UsedApi::kVk: {
312 if (!mColorBufferVk) {
313 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
314 }
315 return vk::borrowColorBufferForDisplay(getHndl());
316 }
317 }
318 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented";
319 return nullptr;
320 }
321
flushFromGl()322 bool ColorBuffer::flushFromGl() {
323 if (!(mColorBufferGl && mColorBufferVk)) {
324 return true;
325 }
326
327 if (mGlAndVkAreSharingExternalMemory) {
328 return true;
329 }
330
331 // ColorBufferGl is currently considered the "main" backing. If this changes,
332 // the "main" should be updated from the current contents of the GL backing.
333 mGlTexDirty = true;
334 return true;
335 }
336
flushFromVk()337 bool ColorBuffer::flushFromVk() {
338 if (!(mColorBufferGl && mColorBufferVk)) {
339 return true;
340 }
341
342 if (mGlAndVkAreSharingExternalMemory) {
343 return true;
344 }
345 std::vector<uint8_t> contents;
346 if (!vk::readColorBufferToBytes(mHandle, &contents)) {
347 ERR("Failed to get VK contents for ColorBuffer:%d", mHandle);
348 return false;
349 }
350
351 if (contents.empty()) {
352 return false;
353 }
354
355 #if GFXSTREAM_ENABLE_HOST_GLES
356 if (!mColorBufferGl->replaceContents(contents.data(), contents.size())) {
357 ERR("Failed to set GL contents for ColorBuffer:%d", mHandle);
358 return false;
359 }
360 #endif
361 mGlTexDirty = false;
362 return true;
363 }
364
flushFromVkBytes(const void * bytes,size_t bytesSize)365 bool ColorBuffer::flushFromVkBytes(const void* bytes, size_t bytesSize) {
366 if (!(mColorBufferGl && mColorBufferVk)) {
367 return true;
368 }
369
370 if (mGlAndVkAreSharingExternalMemory) {
371 return true;
372 }
373
374 #if GFXSTREAM_ENABLE_HOST_GLES
375 if (mColorBufferGl) {
376 if (!mColorBufferGl->replaceContents(bytes, bytesSize)) {
377 ERR("Failed to update ColorBuffer:%d GL backing from VK bytes.", mHandle);
378 return false;
379 }
380 }
381 #endif
382 mGlTexDirty = false;
383 return true;
384 }
385
invalidateForGl()386 bool ColorBuffer::invalidateForGl() {
387 if (!(mColorBufferGl && mColorBufferVk)) {
388 return true;
389 }
390
391 if (mGlAndVkAreSharingExternalMemory) {
392 return true;
393 }
394
395 // ColorBufferGl is currently considered the "main" backing. If this changes,
396 // the GL backing should be updated from the "main" backing.
397 return true;
398 }
399
invalidateForVk()400 bool ColorBuffer::invalidateForVk() {
401 if (!(mColorBufferGl && mColorBufferVk)) {
402 return true;
403 }
404
405 if (mGlAndVkAreSharingExternalMemory) {
406 return true;
407 }
408
409 if (!mGlTexDirty) {
410 return true;
411 }
412
413 #if GFXSTREAM_ENABLE_HOST_GLES
414 std::size_t contentsSize = 0;
415 if (!mColorBufferGl->readContents(&contentsSize, nullptr)) {
416 ERR("Failed to get GL contents size for ColorBuffer:%d", mHandle);
417 return false;
418 }
419
420 std::vector<uint8_t> contents(contentsSize, 0);
421
422 if (!mColorBufferGl->readContents(&contentsSize, contents.data())) {
423 ERR("Failed to get GL contents for ColorBuffer:%d", mHandle);
424 return false;
425 }
426
427 if (!mColorBufferVk->updateFromBytes(contents)) {
428 ERR("Failed to set VK contents for ColorBuffer:%d", mHandle);
429 return false;
430 }
431 #endif
432 mGlTexDirty = false;
433 return true;
434 }
435
importNativeResource(void * nativeResource,uint32_t type,bool preserveContent)436 bool ColorBuffer::importNativeResource(void* nativeResource, uint32_t type, bool preserveContent) {
437 switch (type) {
438 case RESOURCE_TYPE_VK_EXT_MEMORY_HANDLE: {
439 if (mColorBufferGl) {
440 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
441 << "Native resource import type %s is invalid when GL emulation is active. "
442 << "Use RESOURCE_TYPE_EGL_NATIVE_PIXMAP of RESOURCE_TYPE_EGL_IMAGE imports "
443 "instead.";
444 return false;
445 } else if (!mColorBufferVk) {
446 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
447 << "Vulkan emulation must be available for RESOURCE_TYPE_VK_EXT_MEMORY_HANDLE "
448 "import.";
449 return false;
450 }
451 return mColorBufferVk->importExtMemoryHandle(nativeResource, type, preserveContent);
452 }
453 default:
454 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
455 << "Unrecognized type for ColorBuffer::importNativeResource.";
456 return false;
457 }
458 }
459
waitSync()460 int ColorBuffer::waitSync() {
461 if (mColorBufferGl) {
462 return -1;
463 }
464
465 if (!mColorBufferVk) {
466 return -1;
467 }
468
469 return mColorBufferVk->waitSync();
470 }
471
exportBlob()472 std::optional<BlobDescriptorInfo> ColorBuffer::exportBlob() {
473 if (!mColorBufferVk) {
474 return std::nullopt;
475 }
476
477 return mColorBufferVk->exportBlob();
478 }
479
480 #if GFXSTREAM_ENABLE_HOST_GLES
glOpBlitFromCurrentReadBuffer()481 bool ColorBuffer::glOpBlitFromCurrentReadBuffer() {
482 if (!mColorBufferGl) {
483 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
484 }
485
486 touch();
487
488 return mColorBufferGl->blitFromCurrentReadBuffer();
489 }
490
glOpBindToTexture()491 bool ColorBuffer::glOpBindToTexture() {
492 if (!mColorBufferGl) {
493 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
494 }
495
496 touch();
497
498 return mColorBufferGl->bindToTexture();
499 }
500
glOpBindToTexture2()501 bool ColorBuffer::glOpBindToTexture2() {
502 if (!mColorBufferGl) {
503 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
504 }
505
506 return mColorBufferGl->bindToTexture2();
507 }
508
glOpBindToRenderbuffer()509 bool ColorBuffer::glOpBindToRenderbuffer() {
510 if (!mColorBufferGl) {
511 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
512 }
513
514 touch();
515
516 return mColorBufferGl->bindToRenderbuffer();
517 }
518
glOpGetTexture()519 GLuint ColorBuffer::glOpGetTexture() {
520 if (!mColorBufferGl) {
521 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
522 }
523
524 touch();
525
526 return mColorBufferGl->getTexture();
527 }
528
glOpReadback(unsigned char * img,bool readbackBgra)529 void ColorBuffer::glOpReadback(unsigned char* img, bool readbackBgra) {
530 if (!mColorBufferGl) {
531 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
532 }
533
534 touch();
535
536 return mColorBufferGl->readback(img, readbackBgra);
537 }
538
glOpReadbackAsync(GLuint buffer,bool readbackBgra)539 void ColorBuffer::glOpReadbackAsync(GLuint buffer, bool readbackBgra) {
540 if (!mColorBufferGl) {
541 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
542 }
543
544 touch();
545
546 mColorBufferGl->readbackAsync(buffer, readbackBgra);
547 }
548
glOpImportEglImage(void * image,bool preserveContent)549 bool ColorBuffer::glOpImportEglImage(void* image, bool preserveContent) {
550 if (!mColorBufferGl) {
551 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
552 }
553
554 return mColorBufferGl->importEglImage(image, preserveContent);
555 }
556
glOpImportEglNativePixmap(void * pixmap,bool preserveContent)557 bool ColorBuffer::glOpImportEglNativePixmap(void* pixmap, bool preserveContent) {
558 if (!mColorBufferGl) {
559 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
560 }
561
562 return mColorBufferGl->importEglNativePixmap(pixmap, preserveContent);
563 }
564
glOpSwapYuvTexturesAndUpdate(GLenum format,GLenum type,FrameworkFormat frameworkFormat,GLuint * textures)565 void ColorBuffer::glOpSwapYuvTexturesAndUpdate(GLenum format, GLenum type,
566 FrameworkFormat frameworkFormat, GLuint* textures) {
567 if (!mColorBufferGl) {
568 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
569 }
570
571 mColorBufferGl->swapYUVTextures(frameworkFormat, textures);
572
573 // This makes ColorBufferGl regenerate the RGBA texture using
574 // YUVConverter::drawConvert() with the updated YUV textures.
575 mColorBufferGl->subUpdate(0, 0, mWidth, mHeight, format, type, nullptr);
576
577 flushFromGl();
578 }
579
glOpReadContents(size_t * outNumBytes,void * outContents)580 bool ColorBuffer::glOpReadContents(size_t* outNumBytes, void* outContents) {
581 if (!mColorBufferGl) {
582 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
583 }
584
585 return mColorBufferGl->readContents(outNumBytes, outContents);
586 }
587
glOpIsFastBlitSupported() const588 bool ColorBuffer::glOpIsFastBlitSupported() const {
589 if (!mColorBufferGl) {
590 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
591 }
592
593 return mColorBufferGl->isFastBlitSupported();
594 }
595
glOpPostLayer(const ComposeLayer & l,int frameWidth,int frameHeight)596 void ColorBuffer::glOpPostLayer(const ComposeLayer& l, int frameWidth, int frameHeight) {
597 if (!mColorBufferGl) {
598 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
599 }
600
601 mColorBufferGl->postLayer(l, frameWidth, frameHeight);
602 }
603
glOpPostViewportScaledWithOverlay(float rotation,float dx,float dy)604 void ColorBuffer::glOpPostViewportScaledWithOverlay(float rotation, float dx, float dy) {
605 if (!mColorBufferGl) {
606 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
607 }
608
609 mColorBufferGl->postViewportScaledWithOverlay(rotation, dx, dy);
610 }
611 #endif
612
613 } // namespace gfxstream
614