// Copyright 2024 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "ANativeWindowEmulated.h" #include namespace gfxstream { EmulatedANativeWindow::EmulatedANativeWindow( uint32_t width, uint32_t height, uint32_t format, std::vector> buffers) : mRefCount(1), mWidth(width), mHeight(height), mFormat(format), mBuffers(std::move(buffers)) { for (auto& buffer : mBuffers) { mBufferQueue.push_back(QueuedAHB{ .ahb = buffer.get(), .fence = -1, }); } } EGLNativeWindowType EmulatedANativeWindow::asEglNativeWindowType() { return reinterpret_cast(this); } uint32_t EmulatedANativeWindow::getWidth() const { return mWidth; } uint32_t EmulatedANativeWindow::getHeight() const { return mHeight; } int EmulatedANativeWindow::getFormat() const { return mFormat; } int EmulatedANativeWindow::queueBuffer(EGLClientBuffer buffer, int fence) { auto ahb = reinterpret_cast(buffer); mBufferQueue.push_back(QueuedAHB{ .ahb = ahb, .fence = fence, }); return 0; } int EmulatedANativeWindow::dequeueBuffer(EGLClientBuffer* buffer, int* fence) { auto queuedAhb = mBufferQueue.front(); mBufferQueue.pop_front(); *buffer = queuedAhb.ahb->asEglClientBuffer(); *fence = queuedAhb.fence; return 0; } int EmulatedANativeWindow::cancelBuffer(EGLClientBuffer buffer) { auto ahb = reinterpret_cast(buffer); mBufferQueue.push_back(QueuedAHB{ .ahb = ahb, .fence = -1, }); return 0; } void EmulatedANativeWindow::acquire() { ++mRefCount; } void EmulatedANativeWindow::release() { --mRefCount; if (mRefCount == 0) { delete this; } } bool EmulatedANativeWindowHelper::isValid(EGLNativeWindowType window) { // TODO: maybe a registry of valid EmulatedANativeWindow-s? (void)window; return true; } bool EmulatedANativeWindowHelper::isValid(EGLClientBuffer buffer) { // TODO: maybe a registry of valid EmulatedAHardwareBuffer-s? (void)buffer; return true; } void EmulatedANativeWindowHelper::acquire(EGLNativeWindowType window) { auto* anw = reinterpret_cast(window); anw->acquire(); } void EmulatedANativeWindowHelper::release(EGLNativeWindowType window) { auto* anw = reinterpret_cast(window); anw->release(); } void EmulatedANativeWindowHelper::acquire(EGLClientBuffer buffer) { // TODO: maybe a registry of valid EmulatedAHardwareBuffer-s? (void)buffer; } void EmulatedANativeWindowHelper::release(EGLClientBuffer buffer) { (void)buffer; } int EmulatedANativeWindowHelper::getConsumerUsage(EGLNativeWindowType window, int* usage) { (void)window; (void)usage; return 0; } void EmulatedANativeWindowHelper::setUsage(EGLNativeWindowType window, int usage) { (void)window; (void)usage; } int EmulatedANativeWindowHelper::getWidth(EGLNativeWindowType window) { auto anw = reinterpret_cast(window); return anw->getWidth(); } int EmulatedANativeWindowHelper::getHeight(EGLNativeWindowType window) { auto anw = reinterpret_cast(window); return anw->getHeight(); } int EmulatedANativeWindowHelper::getWidth(EGLClientBuffer buffer) { auto ahb = reinterpret_cast(buffer); return ahb->getWidth(); } int EmulatedANativeWindowHelper::getHeight(EGLClientBuffer buffer) { auto ahb = reinterpret_cast(buffer); return ahb->getHeight(); } int EmulatedANativeWindowHelper::getFormat(EGLClientBuffer buffer, Gralloc* helper) { (void)helper; auto ahb = reinterpret_cast(buffer); return ahb->getAndroidFormat(); } void EmulatedANativeWindowHelper::setSwapInterval(EGLNativeWindowType window, int interval) { ALOGE("Unimplemented"); (void)window; (void)interval; } int EmulatedANativeWindowHelper::queueBuffer(EGLNativeWindowType window, EGLClientBuffer buffer, int fence) { auto anw = reinterpret_cast(window); return anw->queueBuffer(buffer, fence); } int EmulatedANativeWindowHelper::dequeueBuffer(EGLNativeWindowType window, EGLClientBuffer* buffer, int* fence) { auto anw = reinterpret_cast(window); return anw->dequeueBuffer(buffer, fence); } int EmulatedANativeWindowHelper::cancelBuffer(EGLNativeWindowType window, EGLClientBuffer buffer) { auto anw = reinterpret_cast(window); return anw->cancelBuffer(buffer); } int EmulatedANativeWindowHelper::getHostHandle(EGLClientBuffer buffer, Gralloc*) { auto ahb = reinterpret_cast(buffer); return ahb->getResourceId(); } EGLNativeWindowType EmulatedANativeWindowHelper::createNativeWindowForTesting(Gralloc* gralloc, uint32_t width, uint32_t height) { std::vector> buffers; for (int i = 0; i < 3; i++) { AHardwareBuffer* ahb = nullptr; if (gralloc->allocate(width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM, -1, &ahb) != 0) { ALOGE("Failed to allocate gralloc buffer."); return nullptr; } buffers.emplace_back(reinterpret_cast(ahb)); } return reinterpret_cast( new EmulatedANativeWindow(width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM, std::move(buffers))); } ANativeWindowHelper* createPlatformANativeWindowHelper() { return new EmulatedANativeWindowHelper(); } } // namespace gfxstream