Commit 055f8f2f authored by achaulk@chromium.org's avatar achaulk@chromium.org

ozone: gbm: Add overlay support

The surface builds up a list of overlays as they come in and HDC
is modified to do the page flip + present all overlays in one go.

BUG=380861
NOTRY=true

Review URL: https://codereview.chromium.org/371813004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282662 0039d316-1c4b-4281-b951-d872f2087c98
parent e7cd231b
...@@ -54,6 +54,9 @@ uint32_t DriSurface::GetHandle() const { ...@@ -54,6 +54,9 @@ uint32_t DriSurface::GetHandle() const {
return backbuffer()->handle(); return backbuffer()->handle();
} }
void DriSurface::PreSwapBuffers() {
}
// This call is made after the hardware just started displaying our back buffer. // This call is made after the hardware just started displaying our back buffer.
// We need to update our pointer reference and synchronize the two buffers. // We need to update our pointer reference and synchronize the two buffers.
void DriSurface::SwapBuffers() { void DriSurface::SwapBuffers() {
......
...@@ -32,6 +32,7 @@ class DriSurface : public ScanoutSurface { ...@@ -32,6 +32,7 @@ class DriSurface : public ScanoutSurface {
virtual bool Initialize() OVERRIDE; virtual bool Initialize() OVERRIDE;
virtual uint32_t GetFramebufferId() const OVERRIDE; virtual uint32_t GetFramebufferId() const OVERRIDE;
virtual uint32_t GetHandle() const OVERRIDE; virtual uint32_t GetHandle() const OVERRIDE;
virtual void PreSwapBuffers() OVERRIDE;
virtual void SwapBuffers() OVERRIDE; virtual void SwapBuffers() OVERRIDE;
virtual gfx::Size Size() const OVERRIDE; virtual gfx::Size Size() const OVERRIDE;
......
...@@ -87,7 +87,7 @@ void DriSurfaceAdapter::PresentCanvas(const gfx::Rect& damage) { ...@@ -87,7 +87,7 @@ void DriSurfaceAdapter::PresentCanvas(const gfx::Rect& damage) {
return; return;
UpdateNativeSurface(damage); UpdateNativeSurface(damage);
controller_->SchedulePageFlip(); controller_->SchedulePageFlip(std::vector<OzoneOverlayPlane>(), NULL);
controller_->WaitForPageFlipEvent(); controller_->WaitForPageFlipEvent();
} }
......
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
#include "base/logging.h" #include "base/logging.h"
namespace ui { namespace ui {
namespace {
uint32_t ToFixedPoint(double v) {
// This returns a number in a 16-bit.16-bit fixed point.
return v * 65536.0;
}
} // namespace
DriWrapper::DriWrapper(const char* device_path) { DriWrapper::DriWrapper(const char* device_path) {
fd_ = open(device_path, O_RDWR | O_CLOEXEC); fd_ = open(device_path, O_RDWR | O_CLOEXEC);
...@@ -86,6 +92,27 @@ bool DriWrapper::PageFlip(uint32_t crtc_id, ...@@ -86,6 +92,27 @@ bool DriWrapper::PageFlip(uint32_t crtc_id,
data); data);
} }
bool DriWrapper::PageFlipOverlay(uint32_t crtc_id,
uint32_t framebuffer,
const gfx::Rect& location,
const gfx::RectF& source,
int overlay_plane) {
CHECK(fd_ >= 0);
return !drmModeSetPlane(fd_,
overlay_plane,
crtc_id,
framebuffer,
0,
location.x(),
location.y(),
location.width(),
location.height(),
ToFixedPoint(source.x()),
ToFixedPoint(source.y()),
ToFixedPoint(source.width()),
ToFixedPoint(source.height()));
}
ScopedDrmFramebufferPtr DriWrapper::GetFramebuffer(uint32_t framebuffer) { ScopedDrmFramebufferPtr DriWrapper::GetFramebuffer(uint32_t framebuffer) {
CHECK(fd_ >= 0); CHECK(fd_ >= 0);
return ScopedDrmFramebufferPtr(drmModeGetFB(fd_, framebuffer)); return ScopedDrmFramebufferPtr(drmModeGetFB(fd_, framebuffer));
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include <stdint.h> #include <stdint.h>
#include "base/macros.h" #include "base/macros.h"
#include "ui/gfx/overlay_transform.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_f.h"
#include "ui/ozone/platform/dri/scoped_drm_types.h" #include "ui/ozone/platform/dri/scoped_drm_types.h"
typedef struct _drmEventContext drmEventContext; typedef struct _drmEventContext drmEventContext;
...@@ -67,6 +70,15 @@ class DriWrapper { ...@@ -67,6 +70,15 @@ class DriWrapper {
// will receive when processing the pageflip event. // will receive when processing the pageflip event.
virtual bool PageFlip(uint32_t crtc_id, uint32_t framebuffer, void* data); virtual bool PageFlip(uint32_t crtc_id, uint32_t framebuffer, void* data);
// Schedule an overlay to be show during the page flip for CRTC |crtc_id|.
// |source| location from |framebuffer| will be shown on overlay
// |overlay_plane|, in the bounds specified by |location| on the screen.
virtual bool PageFlipOverlay(uint32_t crtc_id,
uint32_t framebuffer,
const gfx::Rect& location,
const gfx::RectF& source,
int overlay_plane);
// Returns the property with name |name| associated with |connector|. Returns // Returns the property with name |name| associated with |connector|. Returns
// NULL if property not found. If the returned value is valid, it must be // NULL if property not found. If the returned value is valid, it must be
// released using FreeProperty(). // released using FreeProperty().
......
...@@ -79,11 +79,40 @@ bool GbmBuffer::InitializeBuffer(SurfaceFactoryOzone::BufferFormat format, ...@@ -79,11 +79,40 @@ bool GbmBuffer::InitializeBuffer(SurfaceFactoryOzone::BufferFormat format,
return true; return true;
} }
void* GbmBuffer::GetEGLClientBuffer() { bool GbmBuffer::Initialize() {
return bo_; return bo_ != NULL;
} }
int GbmBuffer::GetDmaBufFd() { uint32_t GbmBuffer::GetFramebufferId() const {
return framebuffer_;
}
uint32_t GbmBuffer::GetHandle() const {
return handle_;
}
gfx::Size GbmBuffer::Size() const {
return size_;
}
void GbmBuffer::PreSwapBuffers() {
}
void GbmBuffer::SwapBuffers() {
}
GbmPixmap::GbmPixmap(gbm_device* device, DriWrapper* dri, const gfx::Size& size)
: buffer_(device, dri, size) {
}
GbmPixmap::~GbmPixmap() {
}
void* GbmPixmap::GetEGLClientBuffer() {
return buffer_.bo();
}
int GbmPixmap::GetDmaBufFd() {
return -1; return -1;
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/dri/scanout_surface.h"
#include "ui/ozone/public/native_pixmap.h" #include "ui/ozone/public/native_pixmap.h"
#include "ui/ozone/public/surface_factory_ozone.h" #include "ui/ozone/public/surface_factory_ozone.h"
...@@ -18,18 +19,22 @@ namespace ui { ...@@ -18,18 +19,22 @@ namespace ui {
class DriWrapper; class DriWrapper;
class GbmBuffer : public NativePixmap { class GbmBuffer : public ScanoutSurface {
public: public:
GbmBuffer(gbm_device* device, DriWrapper* dri, const gfx::Size& size); GbmBuffer(gbm_device* device, DriWrapper* dri, const gfx::Size& size);
virtual ~GbmBuffer();
bool InitializeBuffer(SurfaceFactoryOzone::BufferFormat format, bool scanout); bool InitializeBuffer(SurfaceFactoryOzone::BufferFormat format, bool scanout);
// NativePixmap: // ScanoutSurface:
virtual void* GetEGLClientBuffer() OVERRIDE; virtual bool Initialize() OVERRIDE;
virtual int GetDmaBufFd() OVERRIDE; virtual uint32_t GetFramebufferId() const OVERRIDE;
virtual uint32_t GetHandle() const OVERRIDE;
virtual gfx::Size Size() const OVERRIDE;
virtual void PreSwapBuffers() OVERRIDE;
virtual void SwapBuffers() OVERRIDE;
protected: gbm_bo* bo() { return bo_; }
virtual ~GbmBuffer();
private: private:
gbm_device* gbm_device_; gbm_device* gbm_device_;
...@@ -43,6 +48,21 @@ class GbmBuffer : public NativePixmap { ...@@ -43,6 +48,21 @@ class GbmBuffer : public NativePixmap {
gfx::Size size_; gfx::Size size_;
}; };
class GbmPixmap : public NativePixmap {
public:
GbmPixmap(gbm_device* device, DriWrapper* dri, const gfx::Size& size);
virtual ~GbmPixmap();
// NativePixmap:
virtual void* GetEGLClientBuffer() OVERRIDE;
virtual int GetDmaBufFd() OVERRIDE;
GbmBuffer* buffer() { return &buffer_; }
private:
GbmBuffer buffer_;
};
} // namespace ui } // namespace ui
#endif // UI_OZONE_PLATFORM_DRI_GBM_BUFFER_H_ #endif // UI_OZONE_PLATFORM_DRI_GBM_BUFFER_H_
...@@ -81,20 +81,13 @@ gfx::Size GbmSurface::Size() const { ...@@ -81,20 +81,13 @@ gfx::Size GbmSurface::Size() const {
return size_; return size_;
} }
void GbmSurface::SwapBuffers() { // Before scheduling the backbuffer to be scanned out we need to "lock" it.
// If there was a frontbuffer, is no longer active. Release it back to GBM. // When we lock it, GBM will give a pointer to a buffer representing the
if (buffers_[front_buffer_]) // backbuffer. It will also update its information on which buffers can not be
gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]); // used for drawing. The buffer will be released when the page flip event
// occurs (see SwapBuffers). This is called from HardwareDisplayController
// Update the index to the frontbuffer. // before scheduling a page flip.
front_buffer_ ^= 1; void GbmSurface::PreSwapBuffers() {
// We've just released it. Since GBM doesn't guarantee we'll get the same
// buffer back, we set it to NULL so we don't keep track of objects that may
// have been destroyed.
buffers_[front_buffer_ ^ 1] = NULL;
}
void GbmSurface::LockCurrentDrawable() {
CHECK(native_surface_); CHECK(native_surface_);
// Lock the buffer we want to display. // Lock the buffer we want to display.
buffers_[front_buffer_ ^ 1] = gbm_surface_lock_front_buffer(native_surface_); buffers_[front_buffer_ ^ 1] = gbm_surface_lock_front_buffer(native_surface_);
...@@ -109,4 +102,17 @@ void GbmSurface::LockCurrentDrawable() { ...@@ -109,4 +102,17 @@ void GbmSurface::LockCurrentDrawable() {
} }
} }
void GbmSurface::SwapBuffers() {
// If there was a frontbuffer, is no longer active. Release it back to GBM.
if (buffers_[front_buffer_])
gbm_surface_release_buffer(native_surface_, buffers_[front_buffer_]);
// Update the index to the frontbuffer.
front_buffer_ ^= 1;
// We've just released it. Since GBM doesn't guarantee we'll get the same
// buffer back, we set it to NULL so we don't keep track of objects that may
// have been destroyed.
buffers_[front_buffer_ ^ 1] = NULL;
}
} // namespace ui } // namespace ui
...@@ -32,16 +32,9 @@ class GbmSurface : public ScanoutSurface { ...@@ -32,16 +32,9 @@ class GbmSurface : public ScanoutSurface {
virtual uint32_t GetFramebufferId() const OVERRIDE; virtual uint32_t GetFramebufferId() const OVERRIDE;
virtual uint32_t GetHandle() const OVERRIDE; virtual uint32_t GetHandle() const OVERRIDE;
virtual gfx::Size Size() const OVERRIDE; virtual gfx::Size Size() const OVERRIDE;
virtual void PreSwapBuffers() OVERRIDE;
virtual void SwapBuffers() OVERRIDE; virtual void SwapBuffers() OVERRIDE;
// Before scheduling the backbuffer to be scanned out we need to "lock" it.
// When we lock it, GBM will give a pointer to a buffer representing the
// backbuffer. It will also update its information on which buffers can not be
// used for drawing. The buffer will be released when the page flip event
// occurs (see SwapBuffers). This is called from GbmSurfaceFactory before
// scheduling a page flip.
void LockCurrentDrawable();
gbm_surface* native_surface() { return native_surface_; }; gbm_surface* native_surface() { return native_surface_; };
private: private:
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "ui/ozone/platform/dri/hardware_display_controller.h" #include "ui/ozone/platform/dri/hardware_display_controller.h"
#include "ui/ozone/platform/dri/scanout_surface.h" #include "ui/ozone/platform/dri/scanout_surface.h"
#include "ui/ozone/platform/dri/screen_manager.h" #include "ui/ozone/platform/dri/screen_manager.h"
#include "ui/ozone/public/native_pixmap.h"
#include "ui/ozone/public/surface_ozone_egl.h" #include "ui/ozone/public/surface_ozone_egl.h"
namespace ui { namespace ui {
...@@ -39,6 +40,8 @@ class GbmSurfaceAdapter : public ui::SurfaceOzoneEGL { ...@@ -39,6 +40,8 @@ class GbmSurfaceAdapter : public ui::SurfaceOzoneEGL {
private: private:
base::WeakPtr<HardwareDisplayController> controller_; base::WeakPtr<HardwareDisplayController> controller_;
NativePixmapList overlay_refs_;
std::vector<OzoneOverlayPlane> overlays_;
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceAdapter); DISALLOW_COPY_AND_ASSIGN(GbmSurfaceAdapter);
}; };
...@@ -65,24 +68,32 @@ bool GbmSurfaceAdapter::ResizeNativeWindow(const gfx::Size& viewport_size) { ...@@ -65,24 +68,32 @@ bool GbmSurfaceAdapter::ResizeNativeWindow(const gfx::Size& viewport_size) {
bool GbmSurfaceAdapter::OnSwapBuffers() { bool GbmSurfaceAdapter::OnSwapBuffers() {
if (!controller_) if (!controller_)
return false; return false;
bool flip_succeeded =
static_cast<GbmSurface*>(controller_->surface())->LockCurrentDrawable(); controller_->SchedulePageFlip(overlays_, &overlay_refs_);
if (controller_->SchedulePageFlip()) { overlays_.clear();
if (flip_succeeded)
controller_->WaitForPageFlipEvent(); controller_->WaitForPageFlipEvent();
return true; return flip_succeeded;
}
return false;
} }
bool GbmSurfaceAdapter::ScheduleOverlayPlane( bool GbmSurfaceAdapter::ScheduleOverlayPlane(
int plane_z_order, int plane_z_order,
gfx::OverlayTransform plane_transform, gfx::OverlayTransform plane_transform,
scoped_refptr<ui::NativePixmap> buffer, scoped_refptr<NativePixmap> buffer,
const gfx::Rect& display_bounds, const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) { const gfx::RectF& crop_rect) {
NOTIMPLEMENTED(); GbmPixmap* pixmap = static_cast<GbmPixmap*>(buffer.get());
return false; if (!pixmap) {
LOG(ERROR) << "ScheduleOverlayPlane passed NULL buffer";
return false;
}
overlays_.push_back(OzoneOverlayPlane(pixmap->buffer(),
plane_z_order,
plane_transform,
display_bounds,
crop_rect));
overlay_refs_.push_back(buffer);
return true;
} }
scoped_ptr<gfx::VSyncProvider> GbmSurfaceAdapter::CreateVSyncProvider() { scoped_ptr<gfx::VSyncProvider> GbmSurfaceAdapter::CreateVSyncProvider() {
...@@ -91,9 +102,11 @@ scoped_ptr<gfx::VSyncProvider> GbmSurfaceAdapter::CreateVSyncProvider() { ...@@ -91,9 +102,11 @@ scoped_ptr<gfx::VSyncProvider> GbmSurfaceAdapter::CreateVSyncProvider() {
} // namespace } // namespace
GbmSurfaceFactory::GbmSurfaceFactory() GbmSurfaceFactory::GbmSurfaceFactory(bool allow_surfaceless)
: DriSurfaceFactory(NULL, NULL), : DriSurfaceFactory(NULL, NULL),
device_(NULL) {} device_(NULL),
allow_surfaceless_(allow_surfaceless) {
}
GbmSurfaceFactory::~GbmSurfaceFactory() {} GbmSurfaceFactory::~GbmSurfaceFactory() {}
...@@ -176,11 +189,15 @@ scoped_ptr<ui::SurfaceOzoneEGL> GbmSurfaceFactory::CreateEGLSurfaceForWidget( ...@@ -176,11 +189,15 @@ scoped_ptr<ui::SurfaceOzoneEGL> GbmSurfaceFactory::CreateEGLSurfaceForWidget(
scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmap( scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
gfx::Size size, gfx::Size size,
BufferFormat format) { BufferFormat format) {
scoped_refptr<GbmBuffer> buf = new GbmBuffer(device_, drm_, size); scoped_refptr<GbmPixmap> buf = new GbmPixmap(device_, drm_, size);
if (!buf->InitializeBuffer(format, true)) { if (!buf->buffer()->InitializeBuffer(format, true)) {
return NULL; return NULL;
} }
return buf; return buf;
} }
bool GbmSurfaceFactory::CanShowPrimaryPlaneAsOverlay() {
return allow_surfaceless_;
}
} // namespace ui } // namespace ui
...@@ -13,7 +13,7 @@ namespace ui { ...@@ -13,7 +13,7 @@ namespace ui {
class GbmSurfaceFactory : public DriSurfaceFactory { class GbmSurfaceFactory : public DriSurfaceFactory {
public: public:
GbmSurfaceFactory(); GbmSurfaceFactory(bool allow_surfaceless);
virtual ~GbmSurfaceFactory(); virtual ~GbmSurfaceFactory();
void InitializeGpu(DriWrapper* dri, void InitializeGpu(DriWrapper* dri,
...@@ -32,9 +32,11 @@ class GbmSurfaceFactory : public DriSurfaceFactory { ...@@ -32,9 +32,11 @@ class GbmSurfaceFactory : public DriSurfaceFactory {
virtual scoped_refptr<ui::NativePixmap> CreateNativePixmap( virtual scoped_refptr<ui::NativePixmap> CreateNativePixmap(
gfx::Size size, gfx::Size size,
BufferFormat format) OVERRIDE; BufferFormat format) OVERRIDE;
virtual bool CanShowPrimaryPlaneAsOverlay() OVERRIDE;
private: private:
gbm_device* device_; // Not owned. gbm_device* device_; // Not owned.
bool allow_surfaceless_;
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceFactory); DISALLOW_COPY_AND_ASSIGN(GbmSurfaceFactory);
}; };
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "ui/ozone/platform/dri/dri_buffer.h" #include "ui/ozone/platform/dri/dri_buffer.h"
#include "ui/ozone/platform/dri/dri_wrapper.h" #include "ui/ozone/platform/dri/dri_wrapper.h"
#include "ui/ozone/platform/dri/scanout_surface.h" #include "ui/ozone/platform/dri/scanout_surface.h"
#include "ui/ozone/public/native_pixmap.h"
namespace ui { namespace ui {
...@@ -46,6 +47,19 @@ void HandlePageFlipEvent(int fd, ...@@ -46,6 +47,19 @@ void HandlePageFlipEvent(int fd,
} // namespace } // namespace
OzoneOverlayPlane::OzoneOverlayPlane(ScanoutSurface* scanout,
int z_order,
gfx::OverlayTransform plane_transform,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect)
: scanout(scanout),
z_order(z_order),
plane_transform(plane_transform),
display_bounds(display_bounds),
crop_rect(crop_rect),
overlay_plane(0) {
}
HardwareDisplayController::HardwareDisplayController( HardwareDisplayController::HardwareDisplayController(
DriWrapper* drm, DriWrapper* drm,
uint32_t connector_id, uint32_t connector_id,
...@@ -112,15 +126,54 @@ void HardwareDisplayController::Disable() { ...@@ -112,15 +126,54 @@ void HardwareDisplayController::Disable() {
is_disabled_ = true; is_disabled_ = true;
} }
bool HardwareDisplayController::SchedulePageFlip() { ScanoutSurface* HardwareDisplayController::GetPrimaryPlane(
CHECK(surface_); const std::vector<OzoneOverlayPlane>& overlays) {
if (!is_disabled_ && !drm_->PageFlip(crtc_id_, ScanoutSurface* primary = surface_.get();
surface_->GetFramebufferId(), for (size_t i = 0; i < overlays.size(); i++) {
this)) { const OzoneOverlayPlane& plane = overlays[i];
if (plane.z_order == 0) {
return plane.scanout;
}
}
return primary;
}
bool HardwareDisplayController::SchedulePageFlip(
const std::vector<OzoneOverlayPlane>& overlays,
NativePixmapList* references) {
ScanoutSurface* primary = GetPrimaryPlane(overlays);
CHECK(primary);
primary->PreSwapBuffers();
if (!is_disabled_ &&
!drm_->PageFlip(crtc_id_, primary->GetFramebufferId(), this)) {
LOG(ERROR) << "Cannot page flip: " << strerror(errno); LOG(ERROR) << "Cannot page flip: " << strerror(errno);
return false; return false;
} }
current_overlay_references_.clear();
if (references)
current_overlay_references_.swap(*references);
for (size_t i = 0; i < overlays.size(); i++) {
const OzoneOverlayPlane& plane = overlays[i];
if (!plane.overlay_plane)
continue;
const gfx::Size& size = plane.scanout->Size();
gfx::RectF crop_rect = plane.crop_rect;
crop_rect.Scale(size.width(), size.height());
if (!drm_->PageFlipOverlay(crtc_id_,
plane.scanout->GetFramebufferId(),
plane.display_bounds,
crop_rect,
plane.overlay_plane)) {
LOG(ERROR) << "Cannot display on overlay: " << strerror(errno);
return false;
}
}
return true; return true;
} }
......
...@@ -21,8 +21,26 @@ class Point; ...@@ -21,8 +21,26 @@ class Point;
namespace ui { namespace ui {
class NativePixmap;
class ScanoutSurface; class ScanoutSurface;
typedef std::vector<scoped_refptr<NativePixmap> > NativePixmapList;
struct OzoneOverlayPlane {
OzoneOverlayPlane(ScanoutSurface* scanout,
int z_order,
gfx::OverlayTransform plane_transform,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect);
ScanoutSurface* scanout;
int z_order;
gfx::OverlayTransform plane_transform;
gfx::Rect display_bounds;
gfx::RectF crop_rect;
int overlay_plane;
};
// The HDCOz will handle modesettings and scannout operations for hardware // The HDCOz will handle modesettings and scannout operations for hardware
// devices. // devices.
// //
...@@ -114,7 +132,8 @@ class HardwareDisplayController ...@@ -114,7 +132,8 @@ class HardwareDisplayController
// called again before the page flip occurrs. // called again before the page flip occurrs.
// //
// Returns true if the page flip was successfully registered, false otherwise. // Returns true if the page flip was successfully registered, false otherwise.
bool SchedulePageFlip(); bool SchedulePageFlip(const std::vector<OzoneOverlayPlane>& overlays,
NativePixmapList* references);
// TODO(dnicoara) This should be on the MessageLoop when Ozone can have // TODO(dnicoara) This should be on the MessageLoop when Ozone can have
// BeginFrame can be triggered explicitly by Ozone. // BeginFrame can be triggered explicitly by Ozone.
...@@ -150,6 +169,11 @@ class HardwareDisplayController ...@@ -150,6 +169,11 @@ class HardwareDisplayController
}; };
private: private:
ScanoutSurface* GetPrimaryPlane(
const std::vector<OzoneOverlayPlane>& overlays);
NativePixmapList current_overlay_references_;
// Object containing the connection to the graphics device and wraps the API // Object containing the connection to the graphics device and wraps the API
// calls to control it. // calls to control it.
DriWrapper* drm_; DriWrapper* drm_;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ui/ozone/platform/dri/hardware_display_controller.h" #include "ui/ozone/platform/dri/hardware_display_controller.h"
#include "ui/ozone/platform/dri/test/mock_dri_surface.h" #include "ui/ozone/platform/dri/test/mock_dri_surface.h"
#include "ui/ozone/platform/dri/test/mock_dri_wrapper.h" #include "ui/ozone/platform/dri/test/mock_dri_wrapper.h"
#include "ui/ozone/public/native_pixmap.h"
namespace { namespace {
...@@ -18,6 +19,7 @@ const drmModeModeInfo kDefaultMode = ...@@ -18,6 +19,7 @@ const drmModeModeInfo kDefaultMode =
{0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}}; {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
const gfx::Size kDefaultModeSize(kDefaultMode.hdisplay, kDefaultMode.vdisplay); const gfx::Size kDefaultModeSize(kDefaultMode.hdisplay, kDefaultMode.vdisplay);
const gfx::SizeF kDefaultModeSizeF(1.0, 1.0);
} // namespace } // namespace
...@@ -63,7 +65,8 @@ TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) { ...@@ -63,7 +65,8 @@ TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) {
EXPECT_TRUE(surface->Initialize()); EXPECT_TRUE(surface->Initialize());
EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass(), EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass(),
kDefaultMode)); kDefaultMode));
EXPECT_TRUE(controller_->SchedulePageFlip()); EXPECT_TRUE(controller_->SchedulePageFlip(
std::vector<ui::OzoneOverlayPlane>(), NULL));
EXPECT_TRUE(controller_->surface() != NULL); EXPECT_TRUE(controller_->surface() != NULL);
} }
...@@ -88,7 +91,8 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfPageFlipFails) { ...@@ -88,7 +91,8 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfPageFlipFails) {
EXPECT_TRUE(surface->Initialize()); EXPECT_TRUE(surface->Initialize());
EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass(), EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass(),
kDefaultMode)); kDefaultMode));
EXPECT_FALSE(controller_->SchedulePageFlip()); EXPECT_FALSE(controller_->SchedulePageFlip(
std::vector<ui::OzoneOverlayPlane>(), NULL));
} }
TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) { TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) {
...@@ -99,7 +103,8 @@ TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) { ...@@ -99,7 +103,8 @@ TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) {
EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass(), EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass(),
kDefaultMode)); kDefaultMode));
controller_->Disable(); controller_->Disable();
EXPECT_TRUE(controller_->SchedulePageFlip()); EXPECT_TRUE(controller_->SchedulePageFlip(
std::vector<ui::OzoneOverlayPlane>(), NULL));
EXPECT_EQ(0, drm_->get_page_flip_call_count()); EXPECT_EQ(0, drm_->get_page_flip_call_count());
surface.reset(new ui::MockDriSurface(drm_.get(), kDefaultModeSize)); surface.reset(new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
...@@ -107,6 +112,58 @@ TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) { ...@@ -107,6 +112,58 @@ TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) {
EXPECT_TRUE(surface->Initialize()); EXPECT_TRUE(surface->Initialize());
EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass(), EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass(),
kDefaultMode)); kDefaultMode));
EXPECT_TRUE(controller_->SchedulePageFlip()); EXPECT_TRUE(controller_->SchedulePageFlip(
std::vector<ui::OzoneOverlayPlane>(), NULL));
EXPECT_EQ(1, drm_->get_page_flip_call_count()); EXPECT_EQ(1, drm_->get_page_flip_call_count());
} }
TEST_F(HardwareDisplayControllerTest, CheckOverlayMainSurfaceReplacement) {
scoped_ptr<ui::ScanoutSurface> surface(
new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
scoped_ptr<ui::ScanoutSurface> overlay(
new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
EXPECT_TRUE(surface->Initialize());
EXPECT_TRUE(
controller_->BindSurfaceToController(surface.Pass(), kDefaultMode));
EXPECT_TRUE(overlay->Initialize());
std::vector<ui::OzoneOverlayPlane> overlays;
std::vector<scoped_refptr<ui::NativePixmap> > overlay_refs;
overlays.push_back(ui::OzoneOverlayPlane(overlay.get(),
0,
gfx::OVERLAY_TRANSFORM_NONE,
gfx::Rect(kDefaultModeSize),
gfx::RectF(kDefaultModeSizeF)));
EXPECT_TRUE(controller_->SchedulePageFlip(overlays, &overlay_refs));
EXPECT_EQ(1, drm_->get_page_flip_call_count());
EXPECT_EQ(0, drm_->get_overlay_flip_call_count());
}
TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) {
scoped_ptr<ui::ScanoutSurface> surface(
new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
scoped_ptr<ui::ScanoutSurface> overlay(
new ui::MockDriSurface(drm_.get(), kDefaultModeSize));
EXPECT_TRUE(surface->Initialize());
EXPECT_TRUE(
controller_->BindSurfaceToController(surface.Pass(), kDefaultMode));
EXPECT_TRUE(overlay->Initialize());
std::vector<ui::OzoneOverlayPlane> overlays;
std::vector<scoped_refptr<ui::NativePixmap> > overlay_refs;
overlays.push_back(ui::OzoneOverlayPlane(overlay.get(),
1,
gfx::OVERLAY_TRANSFORM_NONE,
gfx::Rect(kDefaultModeSize),
gfx::RectF(kDefaultModeSizeF)));
overlays.back().overlay_plane = 1; // Force association with a plane.
EXPECT_TRUE(controller_->SchedulePageFlip(overlays, &overlay_refs));
EXPECT_EQ(1, drm_->get_page_flip_call_count());
EXPECT_EQ(1, drm_->get_overlay_flip_call_count());
}
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "ui/events/ozone/evdev/event_factory_evdev.h" #include "ui/events/ozone/evdev/event_factory_evdev.h"
#include "ui/ozone/platform/dri/cursor_factory_evdev_dri.h" #include "ui/ozone/platform/dri/cursor_factory_evdev_dri.h"
#include "ui/ozone/platform/dri/dri_wrapper.h" #include "ui/ozone/platform/dri/dri_wrapper.h"
#include "ui/ozone/platform/dri/gbm_buffer.h"
#include "ui/ozone/platform/dri/gbm_surface.h" #include "ui/ozone/platform/dri/gbm_surface.h"
#include "ui/ozone/platform/dri/gbm_surface_factory.h" #include "ui/ozone/platform/dri/gbm_surface_factory.h"
#include "ui/ozone/platform/dri/gpu_platform_support_gbm.h" #include "ui/ozone/platform/dri/gpu_platform_support_gbm.h"
...@@ -56,7 +57,7 @@ class GbmSurfaceGenerator : public ScanoutSurfaceGenerator { ...@@ -56,7 +57,7 @@ class GbmSurfaceGenerator : public ScanoutSurfaceGenerator {
return new GbmSurface(device_, dri_, size); return new GbmSurface(device_, dri_, size);
} }
private: protected:
DriWrapper* dri_; // Not owned. DriWrapper* dri_; // Not owned.
// HACK: gbm drivers have broken linkage // HACK: gbm drivers have broken linkage
...@@ -67,9 +68,24 @@ class GbmSurfaceGenerator : public ScanoutSurfaceGenerator { ...@@ -67,9 +68,24 @@ class GbmSurfaceGenerator : public ScanoutSurfaceGenerator {
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceGenerator); DISALLOW_COPY_AND_ASSIGN(GbmSurfaceGenerator);
}; };
class GbmEglImageSurfaceGenerator : public GbmSurfaceGenerator {
public:
GbmEglImageSurfaceGenerator(DriWrapper* dri) : GbmSurfaceGenerator(dri) {}
virtual ~GbmEglImageSurfaceGenerator() {}
virtual ScanoutSurface* Create(const gfx::Size& size) OVERRIDE {
scoped_ptr<GbmBuffer> buffer =
scoped_ptr<GbmBuffer>(new GbmBuffer(device_, dri_, size));
if (!buffer->InitializeBuffer(SurfaceFactoryOzone::RGBA_8888, true)) {
return NULL;
}
return buffer.release();
}
};
class OzonePlatformGbm : public OzonePlatform { class OzonePlatformGbm : public OzonePlatform {
public: public:
OzonePlatformGbm() { OzonePlatformGbm(bool use_surfaceless) : use_surfaceless_(use_surfaceless) {
base::AtExitManager::RegisterTask( base::AtExitManager::RegisterTask(
base::Bind(&base::DeletePointer<OzonePlatformGbm>, this)); base::Bind(&base::DeletePointer<OzonePlatformGbm>, this));
} }
...@@ -107,7 +123,7 @@ class OzonePlatformGbm : public OzonePlatform { ...@@ -107,7 +123,7 @@ class OzonePlatformGbm : public OzonePlatform {
vt_manager_.reset(new VirtualTerminalManager()); vt_manager_.reset(new VirtualTerminalManager());
// Needed since the browser process creates the accelerated widgets and that // Needed since the browser process creates the accelerated widgets and that
// happens through SFO. // happens through SFO.
surface_factory_ozone_.reset(new GbmSurfaceFactory()); surface_factory_ozone_.reset(new GbmSurfaceFactory(use_surfaceless_));
device_manager_ = CreateDeviceManager(); device_manager_ = CreateDeviceManager();
gpu_platform_support_host_.reset(new GpuPlatformSupportHostGbm()); gpu_platform_support_host_.reset(new GpuPlatformSupportHostGbm());
...@@ -119,11 +135,14 @@ class OzonePlatformGbm : public OzonePlatform { ...@@ -119,11 +135,14 @@ class OzonePlatformGbm : public OzonePlatform {
virtual void InitializeGPU() OVERRIDE { virtual void InitializeGPU() OVERRIDE {
dri_.reset(new DriWrapper(kDefaultGraphicsCardPath)); dri_.reset(new DriWrapper(kDefaultGraphicsCardPath));
surface_generator_.reset(new GbmSurfaceGenerator(dri_.get())); if (use_surfaceless_)
surface_generator_.reset(new GbmEglImageSurfaceGenerator(dri_.get()));
else
surface_generator_.reset(new GbmSurfaceGenerator(dri_.get()));
screen_manager_.reset(new ScreenManager(dri_.get(), screen_manager_.reset(new ScreenManager(dri_.get(),
surface_generator_.get())); surface_generator_.get()));
if (!surface_factory_ozone_) if (!surface_factory_ozone_)
surface_factory_ozone_.reset(new GbmSurfaceFactory()); surface_factory_ozone_.reset(new GbmSurfaceFactory(use_surfaceless_));
surface_factory_ozone_->InitializeGpu(dri_.get(), surface_factory_ozone_->InitializeGpu(dri_.get(),
surface_generator_->device(), surface_generator_->device(),
...@@ -142,6 +161,7 @@ class OzonePlatformGbm : public OzonePlatform { ...@@ -142,6 +161,7 @@ class OzonePlatformGbm : public OzonePlatform {
} }
private: private:
bool use_surfaceless_;
scoped_ptr<VirtualTerminalManager> vt_manager_; scoped_ptr<VirtualTerminalManager> vt_manager_;
scoped_ptr<DriWrapper> dri_; scoped_ptr<DriWrapper> dri_;
scoped_ptr<GbmSurfaceGenerator> surface_generator_; scoped_ptr<GbmSurfaceGenerator> surface_generator_;
...@@ -160,6 +180,11 @@ class OzonePlatformGbm : public OzonePlatform { ...@@ -160,6 +180,11 @@ class OzonePlatformGbm : public OzonePlatform {
} // namespace } // namespace
OzonePlatform* CreateOzonePlatformGbm() { return new OzonePlatformGbm; } OzonePlatform* CreateOzonePlatformGbm() {
return new OzonePlatformGbm(false);
}
OzonePlatform* CreateOzonePlatformGbmEglImage() {
return new OzonePlatformGbm(true);
}
} // namespace ui } // namespace ui
...@@ -59,6 +59,9 @@ class ScanoutSurface { ...@@ -59,6 +59,9 @@ class ScanoutSurface {
// Returns true if the initialization is successful, false otherwise. // Returns true if the initialization is successful, false otherwise.
virtual bool Initialize() = 0; virtual bool Initialize() = 0;
// Prepare the surface to be displayed.
virtual void PreSwapBuffers() = 0;
// Swaps the back buffer with the front buffer. // Swaps the back buffer with the front buffer.
virtual void SwapBuffers() = 0; virtual void SwapBuffers() = 0;
......
...@@ -27,6 +27,7 @@ MockDriWrapper::MockDriWrapper(int fd) ...@@ -27,6 +27,7 @@ MockDriWrapper::MockDriWrapper(int fd)
add_framebuffer_call_count_(0), add_framebuffer_call_count_(0),
remove_framebuffer_call_count_(0), remove_framebuffer_call_count_(0),
page_flip_call_count_(0), page_flip_call_count_(0),
overlay_flip_call_count_(0),
set_crtc_expectation_(true), set_crtc_expectation_(true),
add_framebuffer_expectation_(true), add_framebuffer_expectation_(true),
page_flip_expectation_(true) { page_flip_expectation_(true) {
...@@ -79,6 +80,15 @@ bool MockDriWrapper::PageFlip(uint32_t crtc_id, ...@@ -79,6 +80,15 @@ bool MockDriWrapper::PageFlip(uint32_t crtc_id,
return page_flip_expectation_; return page_flip_expectation_;
} }
bool MockDriWrapper::PageFlipOverlay(uint32_t crtc_id,
uint32_t framebuffer,
const gfx::Rect& location,
const gfx::RectF& source,
int overlay_plane) {
overlay_flip_call_count_++;
return true;
}
ScopedDrmPropertyPtr MockDriWrapper::GetProperty(drmModeConnector* connector, ScopedDrmPropertyPtr MockDriWrapper::GetProperty(drmModeConnector* connector,
const char* name) { const char* name) {
return ScopedDrmPropertyPtr(DrmAllocator<drmModePropertyRes>()); return ScopedDrmPropertyPtr(DrmAllocator<drmModePropertyRes>());
......
...@@ -24,6 +24,7 @@ class MockDriWrapper : public ui::DriWrapper { ...@@ -24,6 +24,7 @@ class MockDriWrapper : public ui::DriWrapper {
return remove_framebuffer_call_count_; return remove_framebuffer_call_count_;
} }
int get_page_flip_call_count() const { return page_flip_call_count_; } int get_page_flip_call_count() const { return page_flip_call_count_; }
int get_overlay_flip_call_count() const { return overlay_flip_call_count_; }
void fail_init() { fd_ = -1; } void fail_init() { fd_ = -1; }
void set_set_crtc_expectation(bool state) { set_crtc_expectation_ = state; } void set_set_crtc_expectation(bool state) { set_crtc_expectation_ = state; }
void set_page_flip_expectation(bool state) { page_flip_expectation_ = state; } void set_page_flip_expectation(bool state) { page_flip_expectation_ = state; }
...@@ -49,6 +50,11 @@ class MockDriWrapper : public ui::DriWrapper { ...@@ -49,6 +50,11 @@ class MockDriWrapper : public ui::DriWrapper {
virtual bool PageFlip(uint32_t crtc_id, virtual bool PageFlip(uint32_t crtc_id,
uint32_t framebuffer, uint32_t framebuffer,
void* data) OVERRIDE; void* data) OVERRIDE;
virtual bool PageFlipOverlay(uint32_t crtc_id,
uint32_t framebuffer,
const gfx::Rect& location,
const gfx::RectF& source,
int overlay_plane) OVERRIDE;
virtual ScopedDrmPropertyPtr GetProperty(drmModeConnector* connector, virtual ScopedDrmPropertyPtr GetProperty(drmModeConnector* connector,
const char* name) OVERRIDE; const char* name) OVERRIDE;
virtual bool SetProperty(uint32_t connector_id, virtual bool SetProperty(uint32_t connector_id,
...@@ -69,6 +75,7 @@ class MockDriWrapper : public ui::DriWrapper { ...@@ -69,6 +75,7 @@ class MockDriWrapper : public ui::DriWrapper {
int add_framebuffer_call_count_; int add_framebuffer_call_count_;
int remove_framebuffer_call_count_; int remove_framebuffer_call_count_;
int page_flip_call_count_; int page_flip_call_count_;
int overlay_flip_call_count_;
bool set_crtc_expectation_; bool set_crtc_expectation_;
bool add_framebuffer_expectation_; bool add_framebuffer_expectation_;
......
...@@ -52,8 +52,9 @@ class OZONE_BASE_EXPORT SurfaceOzoneEGL { ...@@ -52,8 +52,9 @@ class OZONE_BASE_EXPORT SurfaceOzoneEGL {
// composition. // composition.
// |buffer| to be presented by the overlay. // |buffer| to be presented by the overlay.
// |display_bounds| specify where it is supposed to be on the screen. // |display_bounds| specify where it is supposed to be on the screen.
// |crop_rect| specifies the region within the buffer to be placed inside // |crop_rect| specifies the region within the buffer to be placed
// |display_bounds|. // inside |display_bounds|. This is specified in texture coordinates, in the
// range of [0,1].
virtual bool ScheduleOverlayPlane(int plane_z_order, virtual bool ScheduleOverlayPlane(int plane_z_order,
gfx::OverlayTransform plane_transform, gfx::OverlayTransform plane_transform,
scoped_refptr<NativePixmap> buffer, scoped_refptr<NativePixmap> buffer,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment