continue;
}
- if (!tizen_pixmap->PeekHandle().picture_id) {
- LOG(ERROR) << "No picture id under mailbox: "
+ if (tizen_pixmap->PeekHandle().picture_id) {
+ pair_candidates.emplace_back(candidate.mailbox,
+ *tizen_pixmap->PeekHandle().picture_id);
+ } else if (tizen_pixmap->PeekHandle().modifier ==
+ ui::kFormatModifierLinear) {
+ // For now, stay with default token, since we should not have multiple
+ // videos without |picture_id|.
+ pair_candidates.emplace_back(candidate.mailbox, base::UnguessableToken{});
+ } else {
+ LOG(ERROR) << "Cannot determine token under mailbox: "
<< candidate.mailbox.ToDebugString();
- continue;
}
- pair_candidates.emplace_back(candidate.mailbox,
- *tizen_pixmap->PeekHandle().picture_id);
}
auto assigned_surfaces =
continue;
}
- in_tree_textures_.erase(*tizen_pixmap->PeekHandle().picture_id);
+ const auto picture_id = tizen_pixmap->PeekHandle().picture_id.value_or(
+ base::UnguessableToken{});
+
+ in_tree_textures_.erase(picture_id);
+
+ const bool has_texture_planes = tizen_pixmap->GetNumberOfPlanes() != 0;
+ const bool is_linear_framebuffer =
+ tizen_pixmap->PeekHandle().modifier == ui::kFormatModifierLinear;
auto prepare_result = surface_proxy->PrepareToRender(
- *tizen_pixmap->PeekHandle().picture_id,
- tizen_pixmap->GetNumberOfPlanes() != 0,
+ picture_id, has_texture_planes && !is_linear_framebuffer,
base::BindRepeating(&OverlayProcessorTizen::NotifyMode, weak_this_,
- *tizen_pixmap->PeekHandle().picture_id));
+ picture_id));
prepare_results_.emplace((*candidates)[i].mailbox,
std::make_pair(surface_proxy, prepare_result));
if (prepare_result != gfx::VideoOutputMode::kOverlay) {
continue;
}
auto* tizen_pixmap = reinterpret_cast<ui::TizenNativePixmap*>(pixmap.get());
- last_promotions_.erase(tizen_pixmap->PeekHandle().picture_id.value());
- if (it->second.second != gfx::VideoOutputMode::kTexture) {
- promotions.emplace(tizen_pixmap->PeekHandle().picture_id.value());
- }
+ if (tizen_pixmap->PeekHandle().picture_id) {
+ last_promotions_.erase(tizen_pixmap->PeekHandle().picture_id.value());
+ if (it->second.second != gfx::VideoOutputMode::kTexture) {
+ promotions.emplace(tizen_pixmap->PeekHandle().picture_id.value());
+ }
- auto collection = plane_collection_manager_->Collection(
- tizen_pixmap->PeekHandle().picture_id.value());
- if (collection) {
- collection->NotifyModeChange(it->second.second);
- } else {
- LOG(ERROR) << "Cannot find overlay: "
- << tizen_pixmap->PeekHandle().picture_id->ToString();
+ auto collection = plane_collection_manager_->Collection(
+ tizen_pixmap->PeekHandle().picture_id.value());
+ if (collection) {
+ collection->NotifyModeChange(it->second.second);
+ } else {
+ LOG(ERROR) << "Cannot find overlay: "
+ << tizen_pixmap->PeekHandle().picture_id->ToString();
+ }
}
-
PaintSingleOnGpu(candidate.mailbox, it->second.first,
OverlayPlaneDataFromCandidate(candidate));
}
}
auto* tizen_pixmap = static_cast<ui::TizenNativePixmap*>(pixmap.get());
- if (!tizen_pixmap->PeekHandle().picture_id) {
- continue;
+ if (tizen_pixmap->PeekHandle().picture_id) {
+ result.emplace(*tizen_pixmap->PeekHandle().picture_id);
+ } else if (tizen_pixmap->PeekHandle().modifier ==
+ ui::kFormatModifierLinear) {
+ result.emplace(base::UnguessableToken{});
}
-
- result.emplace(*tizen_pixmap->PeekHandle().picture_id);
}
}
return result;
plane_size.GetArea(), buffer->ExportFd());
offset += plane_size.GetArea();
}
+
+ constexpr uint64_t kFormatModifierLinear = 0;
+ handle_.modifier = kFormatModifierLinear;
return true;
}
// through Graphic Accelerator. Note that it's not DMA related file
// descriptor, but another platform specific concept.
uint32_t y_phys_data;
+ uint64_t y_phys_offset = 0;
uint32_t y_stride;
uint8_t* uv_data;
// Same as |y_phys_data| except it's handle to UV plane.
uint32_t uv_phys_data;
+ uint64_t uv_phys_offset = 0;
uint32_t uv_stride;
};
gfx::Size size,
gfx::BufferFormat format,
gfx::NativePixmapHandle handle) {
- return base::MakeRefCounted<ui::TizenNativePixmap>(this, std::move(handle),
- plane_collection_manager_);
+ return base::MakeRefCounted<ui::TizenNativePixmap>(
+ this, std::move(handle), size, plane_collection_manager_);
}
scoped_refptr<OutputSurfaceProxy> EflSurfaceFactory::GetSurface(
void OutputSurfaceImpl::Render(const gfx::OverlayPlaneData& overlay_plane_data,
gfx::OverlayRenderData render_data) {
- if (!render_data.plane_id) {
- TIZEN_MEDIA_LOG(ERROR) << "Invalid plane id: " << render_data.plane_id;
- return;
- }
-
if (last_picture_plane_ && render_data.picture_size.IsZero()) {
if (last_picture_plane_ != render_data.plane_id) {
TIZEN_MEDIA_LOG(INFO)
damage_rect_ = overlay_plane_data.damage_rect;
}
+ if (pending_source_change_ || !last_picture_plane_) {
+ if (!SelectRenderingMethod(render_data)) {
+ return;
+ }
+ video_surface_.PreparePlane(render_data, current_rendering_method_);
+ }
+
const bool recalculate_geometry = rotation_changed || picture_size_changed ||
display_bounds_changed ||
crop_rect_changed || damage_changed;
if (!recalculate_geometry && !pending_source_change_ && last_picture_plane_ &&
last_picture_plane_.value() == render_data.plane_id &&
last_picture_timestamp_ &&
- last_picture_timestamp_.value() == render_data.timestamp) {
+ last_picture_timestamp_.value() == render_data.timestamp &&
+ !uses_software_rendering_) {
return;
}
- if (pending_source_change_ || !last_picture_plane_) {
- if (IsSoftwareRenderingCapable(render_data) && render_data.low_latency &&
- rendering_workarounds_.prefer_manual_rendering_for_low_latency) {
- TIZEN_MEDIA_LOG(INFO) << "Use software video rendering method";
- current_rendering_method_ = rendering_software_.get();
- } else {
- TIZEN_MEDIA_LOG(INFO) << "Use direct video rendering method";
- current_rendering_method_ = rendering_direct_.get();
- }
-
- video_surface_.PreparePlane(render_data, current_rendering_method_);
- }
-
// Ensure that new values are set before returning due to the wrong
// framebuffer. It allows for recovery in case some wrong value is
// passed here for some reason.
}
}
+bool OutputSurfaceImpl::SelectRenderingMethod(
+ const gfx::OverlayRenderData& render_data) {
+ const bool supports_software_rendering =
+ IsSoftwareRenderingCapable(render_data);
+ const bool supports_direct_rendering = render_data.plane_id != 0;
+ const bool force_software_rendering =
+ supports_software_rendering && render_data.low_latency &&
+ rendering_workarounds_.prefer_manual_rendering_for_low_latency;
+
+ uses_software_rendering_ = false;
+ if (supports_direct_rendering && !force_software_rendering) {
+ TIZEN_MEDIA_LOG(INFO) << "Use direct video rendering method";
+ current_rendering_method_ = rendering_direct_.get();
+ return true;
+ } else if (supports_software_rendering) {
+ TIZEN_MEDIA_LOG(INFO) << "Use software video rendering method";
+ current_rendering_method_ = rendering_software_.get();
+ uses_software_rendering_ = true;
+ return true;
+ }
+
+ TIZEN_MEDIA_LOG(ERROR) << "Cannot choose rendering method";
+ return false;
+}
+
std::ostream& operator<<(std::ostream& stream,
OutputSurfaceImpl::ScalerState state) {
switch (state) {
void UpdateScalerState(bool muted, bool synced);
+ bool SelectRenderingMethod(const gfx::OverlayRenderData& render_data);
+
ScalerState scaler_state_ = ScalerState::kUnknown;
// Indicates last decoder which used this surface.
Plane plane_;
+ bool uses_software_rendering_ = false;
+
const RenderingWorkarounds rendering_workarounds_;
};
#ifndef UI_OZONE_PLATFORM_EFL_OUTPUT_SURFACE_STATE_H_
#define UI_OZONE_PLATFORM_EFL_OUTPUT_SURFACE_STATE_H_
+#include <optional>
+
#include "base/functional/callback_forward.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
picture_usage_ = PictureUsage::kRender;
last_picture_id_ = collection_token;
}
- void reset_using() { last_picture_id_ = base::UnguessableToken::Null(); }
+ void reset_using() { last_picture_id_.reset(); }
// Before calling this method, state should be verified.
ui::OutputSurfaceProxy& surface() { return *surface_; }
// Token identification of client. Note it should be used only when
// |IsUsedByClient| returns true.
- const base::UnguessableToken& ClientToken() const { return last_picture_id_; }
+ const base::UnguessableToken& ClientToken() const {
+ return last_picture_id_.value();
+ }
// Returns true iff scaler is fully allocated and used by compositor
// to render decoded video frames.
base::DeadlineTimer removing_timer_;
PictureUsage picture_usage_;
- base::UnguessableToken last_picture_id_;
+ std::optional<base::UnguessableToken> last_picture_id_;
};
} // namespace ui
TizenNativePixmap::TizenNativePixmap(
ui::EflSurfaceFactory* surface_factory,
gfx::NativePixmapHandle handle,
+ gfx::Size size,
scoped_refptr<gfx::TizenPlaneCollectionManager> plane_collection_manager)
: handle_(std::move(handle)),
+ size_(size),
plane_collection_manager_(plane_collection_manager),
surface_factory_(surface_factory) {}
}
gfx::Size TizenNativePixmap::GetBufferSize() const {
- // TODO(j.gajownik2)
- return gfx::Size();
+ return size_;
}
uint32_t TizenNativePixmap::GetUniqueId() const {
return gfx::CloneHandleForIPC(handle_);
}
+bool TizenNativePixmap::ScheduleSoftwareOverlayPlane(
+ gfx::AcceleratedWidget widget,
+ const gfx::OverlayPlaneData& overlay_plane_data) {
+ auto surface = surface_factory_->GetSurface(widget);
+ if (!surface) {
+ return true;
+ }
+
+ gfx::OverlayRenderData render_data;
+ render_data.plane_id = 0;
+ render_data.picture_size = size_;
+
+ auto y_buffer_holder =
+ gfx::TizenGpuBuffer::ImportFromFd(handle_.planes[0].fd);
+ if (!y_buffer_holder) {
+ LOG(ERROR) << "Cannot import y buffer";
+ return false;
+ }
+ auto y_buffer = y_buffer_holder->Release();
+
+ auto uv_buffer_holder =
+ gfx::TizenGpuBuffer::ImportFromFd(handle_.planes[1].fd);
+ if (!uv_buffer_holder) {
+ LOG(ERROR) << "Cannot import uv buffer";
+ return false;
+ }
+ auto uv_buffer = uv_buffer_holder->Release();
+
+ media::NV12Data nv12_data;
+ nv12_data.y_phys_data = tbm_bo_get_handle(y_buffer.get(), TBM_DEVICE_2D).u32;
+ nv12_data.y_stride = handle_.planes[0].stride;
+ nv12_data.y_phys_offset = handle_.planes[0].offset;
+ nv12_data.uv_phys_data =
+ tbm_bo_get_handle(uv_buffer.get(), TBM_DEVICE_2D).u32;
+ nv12_data.uv_stride = handle_.planes[1].stride;
+ nv12_data.uv_phys_offset = handle_.planes[1].offset;
+ render_data.nv12_data = &nv12_data;
+ surface->Render(overlay_plane_data, render_data);
+ return true;
+}
+
bool TizenNativePixmap::ScheduleOverlayPlane(
gfx::AcceleratedWidget widget,
const gfx::OverlayPlaneData& overlay_plane_data,
std::vector<gfx::GpuFence> /* acquire_fences */,
std::vector<gfx::GpuFence> /* release_fences */) {
+ if (handle_.modifier == kFormatModifierLinear) {
+ return ScheduleSoftwareOverlayPlane(widget, overlay_plane_data);
+ }
+
CHECK(handle_.picture_id);
auto collection = plane_collection_manager_->Collection(*handle_.picture_id);
if (!collection) {
class EflSurfaceFactory;
+constexpr const uint64_t kFormatModifierLinear = 0;
+
class TizenNativePixmap : public gfx::NativePixmap {
public:
explicit TizenNativePixmap(
ui::EflSurfaceFactory* surface_factory,
gfx::NativePixmapHandle handle,
+ gfx::Size size,
scoped_refptr<gfx::TizenPlaneCollectionManager> plane_collection_manager);
TizenNativePixmap(const TizenNativePixmap&) = delete;
gfx::NativePixmapHandle& PeekHandle() { return handle_; }
const gfx::NativePixmapHandle& PeekHandle() const { return handle_; }
- bool SupportsOverlayPlane() const { return handle_.picture_id.has_value(); }
+ bool SupportsOverlayPlane() const {
+ return handle_.picture_id.has_value() ||
+ handle_.modifier == kFormatModifierLinear;
+ }
private:
+ bool ScheduleSoftwareOverlayPlane(
+ gfx::AcceleratedWidget widget,
+ const gfx::OverlayPlaneData& overlay_plane_data);
+
gfx::NativePixmapHandle handle_;
+ const gfx::Size size_;
scoped_refptr<gfx::TizenPlaneCollectionManager> plane_collection_manager_;
ui::EflSurfaceFactory* surface_factory_;
};
const gfx::OverlayRenderData& render_data,
void* video_sink,
void* bufmgr) {
- constexpr const size_t kMaxDisplayBuffers = 8;
+ constexpr const size_t kMaxDisplayBuffers = 3;
+ constexpr const size_t kMaxDisplayBuffersForLowLatency = 5;
+ const size_t max_display_buffers = render_data.low_latency
+ ? kMaxDisplayBuffersForLowLatency
+ : kMaxDisplayBuffers;
- for (size_t i = display_buffers_.size(); i < kMaxDisplayBuffers; ++i) {
+ for (size_t i = display_buffers_.size(); i < max_display_buffers; ++i) {
constexpr size_t kPlaneY = 0;
constexpr size_t kPlaneUV = 1;
// Actual allocation size does not matter, any value might be provided.
display_buffers_[current_index_].y->CopyFrom(
render_data.nv12_data->y_phys_data, render_data.nv12_data->y_stride,
fb_bytes_per_line_, render_data.picture_size.width(),
- render_data.picture_size.height());
+ render_data.picture_size.height(), render_data.nv12_data->y_phys_offset);
display_buffers_[current_index_].uv->CopyFrom(
render_data.nv12_data->uv_phys_data, render_data.nv12_data->uv_stride,
fb_bytes_per_line_, render_data.picture_size.width(),
- render_data.picture_size.height() / 2);
+ render_data.picture_size.height() / 2,
+ render_data.nv12_data->uv_phys_offset);
dec_info_.width = render_data.picture_size.width();
dec_info_.height = render_data.picture_size.height();