blob: 3abb134d1555454d6b453afc94f5bd162cb79ed9 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.h"
#include "base/android/android_hardware_buffer_compat.h"
#include "base/android/scoped_hardware_buffer_handle.h"
#include "base/logging.h"
#include "gpu/command_buffer/service/ahardwarebuffer_utils.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_bindings.h"
namespace gpu {
// Implementation of SharedImageBacking that holds an AHardwareBuffer. This
// can be used to create a GL texture or a VK Image from the AHardwareBuffer
// backing.
class SharedImageBackingAHardwareBuffer : public SharedImageBacking {
public:
SharedImageBackingAHardwareBuffer(
const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
base::android::ScopedHardwareBufferHandle handle)
: SharedImageBacking(mailbox, format, size, color_space, usage),
hardware_buffer_handle_(std::move(handle)) {
DCHECK(hardware_buffer_handle_.is_valid());
}
~SharedImageBackingAHardwareBuffer() override {
// Check to make sure buffer is explicitly destroyed using Destroy() api
// before this destructor is called.
DCHECK(!hardware_buffer_handle_.is_valid());
}
bool IsCleared() const override { return is_cleared_; }
void SetCleared() override { is_cleared_ = true; }
bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override {
DCHECK(hardware_buffer_handle_.is_valid());
// Legacy mailbox is not supported.
return false;
}
void Destroy() override {
DCHECK(hardware_buffer_handle_.is_valid());
hardware_buffer_handle_.reset();
}
private:
base::android::ScopedHardwareBufferHandle hardware_buffer_handle_;
// TODO(vikassoni): In future when we add begin/end write support, we will
// need to properly use this flag to pass the is_cleared_ information to
// the GL texture representation while begin write and back to this class from
// the GL texture represntation after end write. This is because this class
// will not know if SetCleared() arrives during begin write happening on GL
// texture representation.
bool is_cleared_ = false;
DISALLOW_COPY_AND_ASSIGN(SharedImageBackingAHardwareBuffer);
};
SharedImageBackingFactoryAHardwareBuffer::
SharedImageBackingFactoryAHardwareBuffer(
const GpuDriverBugWorkarounds& workarounds) {
// TODO(vikassoni): We are using below GL api calls for now as Vulkan mode
// doesn't exist. Once we have vulkan support, we shouldn't query GL in this
// code until we are asked to make a GL representation (or allocate a backing
// for import into GL)? We may use an AHardwareBuffer exclusively with Vulkan,
// where there is no need to require that a GL context is current. Maybe we
// can lazy init this if someone tries to create an AHardwareBuffer with
// SHARED_IMAGE_USAGE_GLES2 || !gpu_preferences.enable_vulkan. When in Vulkan
// mode, we should only need this with GLES2.
gl::GLApi* api = gl::g_current_gl_context;
api->glGetIntegervFn(GL_MAX_TEXTURE_SIZE, &max_gl_texture_size_);
// TODO(vikassoni): Check vulkan image size restrictions also.
if (workarounds.max_texture_size) {
max_gl_texture_size_ =
std::min(max_gl_texture_size_, workarounds.max_texture_size);
}
}
SharedImageBackingFactoryAHardwareBuffer::
~SharedImageBackingFactoryAHardwareBuffer() = default;
std::unique_ptr<SharedImageBacking>
SharedImageBackingFactoryAHardwareBuffer::CreateSharedImage(
const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) {
DCHECK(base::AndroidHardwareBufferCompat::IsSupportAvailable());
// Check if the format is supported by AHardwareBuffer.
// TODO(vikassoni): We need to check if the equivalent GL texture format
// and VK image format support is available in the underlying hardware. Else
// we might not be able to use this AHB as a gl texture or VK Image.
// Additionally we also need to check usage flags to determine the format.
if (!AHardwareBufferSupportedFormat(format)) {
LOG(ERROR) << "viz::ResourceFormat " << format
<< "not supported by AHardwareBuffer";
return nullptr;
}
// Check for size restrictions.
// TODO(vikassoni): Check for VK size restrictions for VK import, GL size
// restrictions for GL import OR both if this backing is needed to be used
// with both GL and VK.
if (size.width() < 1 || size.height() < 1 ||
size.width() > max_gl_texture_size_ ||
size.height() > max_gl_texture_size_) {
LOG(ERROR) << "CreateSharedImage: invalid size";
return nullptr;
}
// Setup AHardwareBuffer.
AHardwareBuffer* buffer = nullptr;
AHardwareBuffer_Desc hwb_desc;
hwb_desc.width = size.width();
hwb_desc.height = size.height();
hwb_desc.format = AHardwareBufferFormat(format);
// Set usage so that gpu can both read as a texture/write as a framebuffer
// attachment. TODO(vikassoni): Find out if we need to set some more usage
// flags based on the usage params in the current function call.
hwb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
// Number of images in an image array.
hwb_desc.layers = 1;
// The following three are not used here.
hwb_desc.stride = 0;
hwb_desc.rfu0 = 0;
hwb_desc.rfu1 = 0;
// Allocate an AHardwareBuffer.
base::AndroidHardwareBufferCompat::GetInstance().Allocate(&hwb_desc, &buffer);
if (!buffer) {
LOG(ERROR) << "Failed to allocate AHardwareBuffer";
return nullptr;
}
auto backing = std::make_unique<SharedImageBackingAHardwareBuffer>(
mailbox, format, size, color_space, usage,
base::android::ScopedHardwareBufferHandle::Adopt(buffer));
return backing;
}
} // namespace gpu