merge in mnc-dr-release history after reset to mnc-dr-dev
diff --git a/drm_hwcomposer.h b/drm_hwcomposer.h
index cebdbee..fdf389b 100644
--- a/drm_hwcomposer.h
+++ b/drm_hwcomposer.h
@@ -22,6 +22,7 @@
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
+#include "seperate_rects.h"
struct hwc_import_context;
@@ -71,4 +72,202 @@
bool hwc_import_bo_release(int fd, struct hwc_import_context *ctx,
struct hwc_drm_bo *bo);
+namespace android {
+
+class Importer;
+
+class UniqueFd {
+ public:
+ UniqueFd() = default;
+ UniqueFd(int fd) : fd_(fd) {
+ }
+ UniqueFd(UniqueFd &&rhs) {
+ fd_ = rhs.fd_;
+ rhs.fd_ = -1;
+ }
+
+ UniqueFd &operator=(UniqueFd &&rhs) {
+ Set(rhs.Release());
+ return *this;
+ }
+
+ ~UniqueFd() {
+ if (fd_ >= 0)
+ close(fd_);
+ }
+
+ int Release() {
+ int old_fd = fd_;
+ fd_ = -1;
+ return old_fd;
+ }
+
+ int Set(int fd) {
+ if (fd_ >= 0)
+ close(fd_);
+ fd_ = fd;
+ return fd_;
+ }
+
+ void Close() {
+ if (fd_ >= 0)
+ close(fd_);
+ fd_ = -1;
+ }
+
+ int get() {
+ return fd_;
+ }
+
+ private:
+ int fd_ = -1;
+};
+
+struct OutputFd {
+ OutputFd() = default;
+ OutputFd(int *fd) : fd_(fd) {
+ }
+ OutputFd(OutputFd &&rhs) {
+ fd_ = rhs.fd_;
+ rhs.fd_ = NULL;
+ }
+
+ OutputFd &operator=(OutputFd &&rhs);
+
+ int Set(int fd) {
+ if (*fd_ >= 0)
+ close(*fd_);
+ *fd_ = fd;
+ return fd;
+ }
+
+ int get() {
+ return *fd_;
+ }
+
+ private:
+ int *fd_ = NULL;
+};
+
+class DrmHwcBuffer {
+ public:
+ DrmHwcBuffer() = default;
+ DrmHwcBuffer(const hwc_drm_bo &bo, Importer *importer)
+ : bo_(bo), importer_(importer) {
+ }
+ DrmHwcBuffer(DrmHwcBuffer &&rhs) : bo_(rhs.bo_), importer_(rhs.importer_) {
+ rhs.importer_ = NULL;
+ }
+
+ ~DrmHwcBuffer() {
+ Clear();
+ }
+
+ DrmHwcBuffer &operator=(DrmHwcBuffer &&rhs) {
+ Clear();
+ importer_ = rhs.importer_;
+ rhs.importer_ = NULL;
+ bo_ = rhs.bo_;
+ return *this;
+ }
+
+ operator bool() {
+ return importer_ != NULL;
+ }
+
+ hwc_drm_bo *operator->();
+
+ void Clear();
+
+ int ImportBuffer(buffer_handle_t handle, Importer *importer);
+
+ private:
+ hwc_drm_bo bo_;
+ Importer *importer_ = NULL;
+};
+
+class DrmHwcNativeHandle {
+ public:
+ DrmHwcNativeHandle() = default;
+
+ DrmHwcNativeHandle(const gralloc_module_t *gralloc, native_handle_t *handle)
+ : gralloc_(gralloc), handle_(handle) {
+ }
+
+ DrmHwcNativeHandle(DrmHwcNativeHandle &&rhs) {
+ gralloc_ = rhs.gralloc_;
+ rhs.gralloc_ = NULL;
+ handle_ = rhs.handle_;
+ rhs.handle_ = NULL;
+ }
+
+ ~DrmHwcNativeHandle();
+
+ DrmHwcNativeHandle &operator=(DrmHwcNativeHandle &&rhs) {
+ Clear();
+ gralloc_ = rhs.gralloc_;
+ rhs.gralloc_ = NULL;
+ handle_ = rhs.handle_;
+ rhs.handle_ = NULL;
+ return *this;
+ }
+
+ int CopyBufferHandle(buffer_handle_t handle, const gralloc_module_t *gralloc);
+
+ void Clear();
+
+ buffer_handle_t get() const {
+ return handle_;
+ }
+
+ private:
+ const gralloc_module_t *gralloc_ = NULL;
+ native_handle_t *handle_ = NULL;
+};
+
+template <typename T>
+using DrmHwcRect = seperate_rects::Rect<T>;
+
+enum class DrmHwcTransform : uint32_t {
+ kIdentity = 0,
+ kFlipH = HWC_TRANSFORM_FLIP_H,
+ kFlipV = HWC_TRANSFORM_FLIP_V,
+ kRotate90 = HWC_TRANSFORM_ROT_90,
+ kRotate180 = HWC_TRANSFORM_ROT_180,
+ kRotate270 = HWC_TRANSFORM_ROT_270,
+};
+
+enum class DrmHwcBlending : int32_t {
+ kNone = HWC_BLENDING_NONE,
+ kPreMult = HWC_BLENDING_PREMULT,
+ kCoverage = HWC_BLENDING_COVERAGE,
+};
+
+struct DrmHwcLayer {
+ buffer_handle_t sf_handle = NULL;
+ DrmHwcBuffer buffer;
+ DrmHwcNativeHandle handle;
+ DrmHwcTransform transform = DrmHwcTransform::kIdentity;
+ DrmHwcBlending blending = DrmHwcBlending::kNone;
+ uint8_t alpha = 0xff;
+ DrmHwcRect<float> source_crop;
+ DrmHwcRect<int> display_frame;
+ std::vector<DrmHwcRect<int>> source_damage;
+
+ UniqueFd acquire_fence;
+ OutputFd release_fence;
+
+ DrmHwcLayer() = default;
+ DrmHwcLayer(DrmHwcLayer &&rhs) = default;
+
+ int InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
+ const gralloc_module_t *gralloc);
+};
+
+struct DrmHwcDisplayContents {
+ OutputFd retire_fence;
+ std::vector<DrmHwcLayer> layers;
+};
+}
+
#endif
diff --git a/drmcomposition.cpp b/drmcomposition.cpp
index 864c5e5..634b0bb 100644
--- a/drmcomposition.cpp
+++ b/drmcomposition.cpp
@@ -69,15 +69,15 @@
}
int DrmComposition::SetLayers(size_t num_displays,
- const DrmCompositionDisplayLayersMap *maps) {
+ DrmCompositionDisplayLayersMap *maps) {
int ret = 0;
for (size_t display_index = 0; display_index < num_displays;
display_index++) {
- const DrmCompositionDisplayLayersMap &map = maps[display_index];
+ DrmCompositionDisplayLayersMap &map = maps[display_index];
int display = map.display;
ret = composition_map_[display]->SetLayers(
- map.layers, map.num_layers, map.layer_indices, &primary_planes_,
+ map.layers.data(), map.layers.size(), &primary_planes_,
&overlay_planes_);
if (ret)
return ret;
diff --git a/drmcomposition.h b/drmcomposition.h
index 426ced0..a5d9cf1 100644
--- a/drmcomposition.h
+++ b/drmcomposition.h
@@ -22,7 +22,6 @@
#include "drmplane.h"
#include "importer.h"
-#include <deque>
#include <map>
#include <vector>
@@ -33,9 +32,11 @@
struct DrmCompositionDisplayLayersMap {
int display;
- size_t num_layers;
- hwc_layer_1_t *layers;
- size_t *layer_indices;
+ std::vector<DrmHwcLayer> layers;
+
+ DrmCompositionDisplayLayersMap() = default;
+ DrmCompositionDisplayLayersMap(DrmCompositionDisplayLayersMap &&rhs) =
+ default;
};
class DrmComposition {
@@ -44,8 +45,7 @@
int Init(uint64_t frame_no);
- int SetLayers(size_t num_displays,
- const DrmCompositionDisplayLayersMap *maps);
+ int SetLayers(size_t num_displays, DrmCompositionDisplayLayersMap *maps);
int SetDpmsMode(int display, uint32_t dpms_mode);
std::unique_ptr<DrmDisplayComposition> TakeDisplayComposition(int display);
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index c1848e0..457fb5a 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -30,39 +30,18 @@
namespace android {
-static native_handle_t *dup_buffer_handle(buffer_handle_t handle) {
- native_handle_t *new_handle =
- native_handle_create(handle->numFds, handle->numInts);
- if (new_handle == NULL)
- return NULL;
-
- const int *old_data = handle->data;
- int *new_data = new_handle->data;
- for (int i = 0; i < handle->numFds; i++) {
- *new_data = dup(*old_data);
- old_data++;
- new_data++;
- }
- memcpy(new_data, old_data, sizeof(int) * handle->numInts);
-
- return new_handle;
-}
-
-static void free_buffer_handle(native_handle_t *handle) {
- int ret = native_handle_close(handle);
- if (ret)
- ALOGE("Failed to close native handle %d", ret);
- ret = native_handle_delete(handle);
- if (ret)
- ALOGE("Failed to delete native handle %d", ret);
-}
-
-DrmCompositionLayer::DrmCompositionLayer()
- : crtc(NULL), plane(NULL), handle(NULL) {
- memset(&layer, 0, sizeof(layer));
- layer.releaseFenceFd = -1;
- layer.acquireFenceFd = -1;
- memset(&bo, 0, sizeof(bo));
+DrmCompositionLayer::DrmCompositionLayer(DrmCrtc *crtc, DrmHwcLayer &&l)
+ : crtc(crtc),
+ sf_handle(l.sf_handle),
+ buffer(std::move(l.buffer)),
+ handle(std::move(l.handle)),
+ transform(l.transform),
+ blending(l.blending),
+ alpha(l.alpha),
+ source_crop(l.source_crop),
+ display_frame(l.display_frame),
+ source_damage(l.source_damage),
+ acquire_fence(std::move(l.acquire_fence)) {
}
DrmDisplayComposition::DrmDisplayComposition()
@@ -79,20 +58,6 @@
}
DrmDisplayComposition::~DrmDisplayComposition() {
- for (DrmCompositionLayerVector_t::iterator iter = layers_.begin();
- iter != layers_.end(); ++iter) {
- if (importer_ && iter->bo.fb_id)
- importer_->ReleaseBuffer(&iter->bo);
-
- if (iter->handle) {
- gralloc_->unregisterBuffer(gralloc_, iter->handle);
- free_buffer_handle(iter->handle);
- }
-
- if (iter->layer.acquireFenceFd >= 0)
- close(iter->layer.acquireFenceFd);
- }
-
if (timeline_fd_ >= 0) {
FinishComposition();
close(timeline_fd_);
@@ -103,18 +68,11 @@
int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
Importer *importer, uint64_t frame_no) {
drm_ = drm;
- crtc_ = crtc; // Can be NULL if we haven't modeset yet
+ crtc_ = crtc; // Can be NULL if we haven't modeset yet
importer_ = importer;
frame_no_ = frame_no;
- int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
- (const hw_module_t **)&gralloc_);
- if (ret) {
- ALOGE("Failed to open gralloc module %d", ret);
- return ret;
- }
-
- ret = sw_sync_timeline_create();
+ int ret = sw_sync_timeline_create();
if (ret < 0) {
ALOGE("Failed to create sw sync timeline %d", ret);
return ret;
@@ -170,8 +128,7 @@
return ret;
}
-int DrmDisplayComposition::SetLayers(hwc_layer_1_t *layers, size_t num_layers,
- size_t *layer_indices,
+int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers,
std::vector<DrmPlane *> *primary_planes,
std::vector<DrmPlane *> *overlay_planes) {
int ret = 0;
@@ -179,32 +136,10 @@
return -EINVAL;
for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
- hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
+ DrmHwcLayer *layer = &layers[layer_index];
- native_handle_t *handle_copy = dup_buffer_handle(layer->handle);
- if (handle_copy == NULL) {
- ALOGE("Failed to duplicate handle");
- return -ENOMEM;
- }
-
- int ret = gralloc_->registerBuffer(gralloc_, handle_copy);
- if (ret) {
- ALOGE("Failed to register buffer handle %d", ret);
- free_buffer_handle(handle_copy);
- return ret;
- }
-
- layers_.emplace_back();
- DrmCompositionLayer_t *c_layer = &layers_.back();
- c_layer->layer = *layer;
- c_layer->handle = handle_copy;
- c_layer->crtc = crtc_;
-
- ret = importer_->ImportBuffer(layer->handle, &c_layer->bo);
- if (ret) {
- ALOGE("Failed to import handle of layer %d", ret);
- goto fail;
- }
+ layers_.emplace_back(crtc_, std::move(*layer));
+ DrmCompositionLayer *c_layer = &layers_.back();
if (pre_composition_layer_index_ == -1) {
c_layer->plane = TakePlane(crtc_, primary_planes, overlay_planes);
@@ -218,27 +153,19 @@
layers_.emplace_back();
// c_layer's address might have changed when we resized the vector
c_layer = &layers_[layers_.size() - 2];
- DrmCompositionLayer_t &pre_comp_layer = layers_.back();
+ DrmCompositionLayer &pre_comp_layer = layers_.back();
pre_comp_layer.crtc = crtc_;
- hwc_layer_1_t &pre_comp_output_layer = pre_comp_layer.layer;
- memset(&pre_comp_output_layer, 0, sizeof(pre_comp_output_layer));
- pre_comp_output_layer.compositionType = HWC_OVERLAY;
- pre_comp_output_layer.acquireFenceFd = -1;
- pre_comp_output_layer.releaseFenceFd = -1;
- pre_comp_output_layer.planeAlpha = 0xff;
- pre_comp_output_layer.visibleRegionScreen.numRects = 1;
- pre_comp_output_layer.visibleRegionScreen.rects =
- &pre_comp_output_layer.displayFrame;
pre_composition_layer_index_ = layers_.size() - 1;
// This is all to fix up the previous layer, which has now become part
// of the set of pre-composition layers because we are stealing its
// plane.
- DrmCompositionLayer_t &last_c_layer = layers_[layers_.size() - 3];
+ DrmCompositionLayer &last_c_layer = layers_[layers_.size() - 3];
std::swap(pre_comp_layer.plane, last_c_layer.plane);
- hwc_layer_1_t *last_layer = &layers[layer_indices[layer_index - 1]];
- ret = last_layer->releaseFenceFd = CreateNextTimelineFence();
+ OutputFd &last_release_fence = layers[layer_index - 1].release_fence;
+ last_release_fence.Set(CreateNextTimelineFence());
+ ret = last_release_fence.get();
if (ret < 0) {
ALOGE("Could not create release fence %d", ret);
goto fail;
@@ -249,7 +176,8 @@
if (c_layer->plane == NULL) {
// Layers to be pre composited all get the earliest release fences as they
// will get released soonest.
- ret = layer->releaseFenceFd = CreateNextTimelineFence();
+ layer->release_fence.Set(CreateNextTimelineFence());
+ ret = layer->release_fence.get();
if (ret < 0) {
ALOGE("Could not create release fence %d", ret);
goto fail;
@@ -260,22 +188,17 @@
timeline_pre_comp_done_ = timeline_;
for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
- hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
- if (layer->releaseFenceFd >= 0)
+ DrmHwcLayer *layer = &layers[layer_index];
+ if (layer->release_fence.get() >= 0)
continue;
- ret = layer->releaseFenceFd = CreateNextTimelineFence();
+ ret = layer->release_fence.Set(CreateNextTimelineFence());
if (ret < 0) {
ALOGE("Could not create release fence %d", ret);
goto fail;
}
}
- for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
- hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
- layer->acquireFenceFd = -1; // We own this now
- }
-
type_ = DRM_COMPOSITION_TYPE_FRAME;
return 0;
@@ -283,13 +206,7 @@
for (size_t c_layer_index = 0; c_layer_index < layers_.size();
c_layer_index++) {
- DrmCompositionLayer_t &c_layer = layers_[c_layer_index];
- if (c_layer.handle) {
- gralloc_->unregisterBuffer(gralloc_, c_layer.handle);
- free_buffer_handle(c_layer.handle);
- }
- if (c_layer.bo.fb_id)
- importer_->ReleaseBuffer(&c_layer.bo);
+ DrmCompositionLayer &c_layer = layers_[c_layer_index];
if (c_layer.plane != NULL) {
std::vector<DrmPlane *> *return_to =
(c_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY) ? primary_planes
@@ -297,15 +214,9 @@
return_to->insert(return_to->begin() + c_layer_index, c_layer.plane);
}
}
+
layers_.clear();
- for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
- hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
- if (layer->releaseFenceFd >= 0) {
- close(layer->releaseFenceFd);
- layer->releaseFenceFd = -1;
- }
- }
sw_sync_timeline_inc(timeline_fd_, timeline_ - timeline_current_);
timeline_ = timeline_current_;
@@ -322,35 +233,16 @@
int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
layers_.emplace_back();
- DrmCompositionLayer_t &c_layer = layers_.back();
+ DrmCompositionLayer &c_layer = layers_.back();
c_layer.crtc = NULL;
c_layer.plane = plane;
return 0;
}
void DrmDisplayComposition::RemoveNoPlaneLayers() {
- for (auto &comp_layer : layers_) {
- if (comp_layer.plane != NULL)
- continue;
-
- if (importer_ && comp_layer.bo.fb_id) {
- importer_->ReleaseBuffer(&comp_layer.bo);
- }
-
- if (comp_layer.handle) {
- gralloc_->unregisterBuffer(gralloc_, comp_layer.handle);
- free_buffer_handle(comp_layer.handle);
- }
-
- if (comp_layer.layer.acquireFenceFd >= 0) {
- close(comp_layer.layer.acquireFenceFd);
- comp_layer.layer.acquireFenceFd = -1;
- }
- }
-
layers_.erase(
std::remove_if(layers_.begin(), layers_.end(),
- [](DrmCompositionLayer_t &l) { return l.plane == NULL; }),
+ [](DrmCompositionLayer &l) { return l.plane == NULL; }),
layers_.end());
}
@@ -362,7 +254,8 @@
return IncreaseTimelineToPoint(timeline_);
}
-DrmCompositionLayerVector_t *DrmDisplayComposition::GetCompositionLayers() {
+std::vector<DrmCompositionLayer>
+ *DrmDisplayComposition::GetCompositionLayers() {
return &layers_;
}
diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h
index be4ecef..06784f1 100644
--- a/drmdisplaycomposition.h
+++ b/drmdisplaycomposition.h
@@ -37,16 +37,32 @@
DRM_COMPOSITION_TYPE_DPMS,
};
-typedef struct DrmCompositionLayer {
- DrmCompositionLayer();
+struct DrmCompositionLayer {
+ DrmCrtc *crtc = NULL;
+ DrmPlane *plane = NULL;
- hwc_layer_1_t layer;
- hwc_drm_bo_t bo;
- DrmCrtc *crtc;
- DrmPlane *plane;
- native_handle_t *handle;
-} DrmCompositionLayer_t;
-typedef std::vector<DrmCompositionLayer_t> DrmCompositionLayerVector_t;
+ buffer_handle_t sf_handle = NULL;
+ DrmHwcBuffer buffer;
+ DrmHwcNativeHandle handle;
+ DrmHwcTransform transform = DrmHwcTransform::kIdentity;
+ DrmHwcBlending blending = DrmHwcBlending::kNone;
+ uint8_t alpha = 0xff;
+ DrmHwcRect<float> source_crop;
+ DrmHwcRect<int> display_frame;
+ std::vector<DrmHwcRect<int>> source_damage;
+
+ UniqueFd acquire_fence;
+
+ DrmCompositionLayer() = default;
+ DrmCompositionLayer(DrmCrtc *crtc, DrmHwcLayer &&l);
+ DrmCompositionLayer(DrmCompositionLayer &&l) = default;
+
+ DrmCompositionLayer &operator=(DrmCompositionLayer &&l) = default;
+
+ buffer_handle_t get_usable_handle() const {
+ return handle.get() != NULL ? handle.get() : sf_handle;
+ }
+};
class DrmDisplayComposition {
public:
@@ -58,7 +74,7 @@
DrmCompositionType type() const;
- int SetLayers(hwc_layer_1_t *layers, size_t num_layers, size_t *layer_indices,
+ int SetLayers(DrmHwcLayer *layers, size_t num_layers,
std::vector<DrmPlane *> *primary_planes,
std::vector<DrmPlane *> *overlay_planes);
int AddPlaneDisable(DrmPlane *plane);
@@ -68,7 +84,7 @@
int SignalPreCompositionDone();
int FinishComposition();
- DrmCompositionLayerVector_t *GetCompositionLayers();
+ std::vector<DrmCompositionLayer> *GetCompositionLayers();
int pre_composition_layer_index() const;
uint32_t dpms_mode() const;
@@ -97,7 +113,7 @@
int timeline_current_;
int timeline_pre_comp_done_;
- DrmCompositionLayerVector_t layers_;
+ std::vector<DrmCompositionLayer> layers_;
int pre_composition_layer_index_;
uint32_t dpms_mode_;
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index b293681..6ee145f 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -146,7 +146,7 @@
}
static bool drm_composition_layer_has_plane(
- const DrmCompositionLayer_t &comp_layer) {
+ const DrmCompositionLayer &comp_layer) {
if (comp_layer.plane != NULL)
if (comp_layer.plane->type() == DRM_PLANE_TYPE_OVERLAY ||
comp_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY)
@@ -155,14 +155,15 @@
}
static bool drm_composition_layer_has_no_plane(
- const DrmCompositionLayer_t &comp_layer) {
+ const DrmCompositionLayer &comp_layer) {
return comp_layer.plane == NULL;
}
int DrmDisplayCompositor::ApplyPreComposite(
DrmDisplayComposition *display_comp) {
int ret = 0;
- DrmCompositionLayerVector_t *layers = display_comp->GetCompositionLayers();
+ std::vector<DrmCompositionLayer> *layers =
+ display_comp->GetCompositionLayers();
DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
if (connector == NULL) {
@@ -185,12 +186,10 @@
return -ENOMEM;
}
- std::vector<hwc_layer_1_t> pre_comp_layers;
+ std::vector<DrmCompositionLayer> pre_comp_layers;
for (auto &comp_layer : *layers) {
if (comp_layer.plane == NULL) {
- pre_comp_layers.push_back(comp_layer.layer);
- pre_comp_layers.back().handle = comp_layer.handle;
- comp_layer.layer.acquireFenceFd = -1;
+ pre_comp_layers.emplace_back(std::move(comp_layer));
}
}
@@ -198,36 +197,26 @@
pre_comp_layers.size(), fb.buffer());
pre_compositor_->Finish();
- for (auto &pre_comp_layer : pre_comp_layers) {
- if (pre_comp_layer.acquireFenceFd >= 0) {
- close(pre_comp_layer.acquireFenceFd);
- pre_comp_layer.acquireFenceFd = -1;
- }
- }
-
if (ret) {
ALOGE("Failed to composite layers");
return ret;
}
- DrmCompositionLayer_t &pre_comp_layer =
+ DrmCompositionLayer &pre_comp_layer =
layers->at(display_comp->pre_composition_layer_index());
- ret = display_comp->importer()->ImportBuffer(fb.buffer()->handle,
- &pre_comp_layer.bo);
+ ret = pre_comp_layer.buffer.ImportBuffer(fb.buffer()->handle,
+ display_comp->importer());
if (ret) {
ALOGE("Failed to import handle of layer %d", ret);
return ret;
}
- hwc_layer_1_t &pre_comp_output_layer = pre_comp_layer.layer;
- pre_comp_output_layer.handle = fb.buffer()->handle;
- pre_comp_output_layer.visibleRegionScreen.rects =
- &pre_comp_output_layer.displayFrame;
- pre_comp_output_layer.sourceCropf.right =
- pre_comp_output_layer.displayFrame.right = fb.buffer()->getWidth();
- pre_comp_output_layer.sourceCropf.bottom =
- pre_comp_output_layer.displayFrame.bottom = fb.buffer()->getHeight();
+ pre_comp_layer.source_crop = DrmHwcRect<float>(0, 0, fb.buffer()->getWidth(),
+ fb.buffer()->getHeight());
+ pre_comp_layer.display_frame =
+ DrmHwcRect<int>(0, 0, fb.buffer()->getWidth(), fb.buffer()->getHeight());
- fb.set_release_fence_fd(pre_comp_output_layer.releaseFenceFd);
+ // TODO(zachr) get a release fence
+ // fb.set_release_fence_fd(pre_comp_layer.release_fence.Release());
framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
display_comp->RemoveNoPlaneLayers();
@@ -250,24 +239,22 @@
return -ENOMEM;
}
- DrmCompositionLayerVector_t *layers = display_comp->GetCompositionLayers();
- for (DrmCompositionLayerVector_t::iterator iter = layers->begin();
- iter != layers->end(); ++iter) {
- hwc_layer_1_t *layer = &iter->layer;
-
- if (layer->acquireFenceFd >= 0) {
- ret = sync_wait(layer->acquireFenceFd, -1);
+ std::vector<DrmCompositionLayer> *layers =
+ display_comp->GetCompositionLayers();
+ for (DrmCompositionLayer &layer : *layers) {
+ int acquire_fence = layer.acquire_fence.get();
+ if (acquire_fence >= 0) {
+ ret = sync_wait(acquire_fence, -1);
if (ret) {
- ALOGE("Failed to wait for acquire %d/%d", layer->acquireFenceFd, ret);
+ ALOGE("Failed to wait for acquire %d/%d", acquire_fence, ret);
drmModePropertySetFree(pset);
return ret;
}
- close(layer->acquireFenceFd);
- layer->acquireFenceFd = -1;
+ layer.acquire_fence.Close();
}
- DrmPlane *plane = iter->plane;
- DrmCrtc *crtc = iter->crtc;
+ DrmPlane *plane = layer.plane;
+ DrmCrtc *crtc = layer.crtc;
// Disable the plane if there's no crtc
if (!crtc) {
@@ -282,28 +269,34 @@
continue;
}
+ if (!layer.buffer) {
+ ALOGE("Expected a valid framebuffer for pset");
+ ret = -EINVAL;
+ break;
+ }
+
uint64_t rotation;
- switch (layer->transform) {
- case HWC_TRANSFORM_FLIP_H:
+ switch (layer.transform) {
+ case DrmHwcTransform::kFlipH:
rotation = 1 << DRM_REFLECT_X;
break;
- case HWC_TRANSFORM_FLIP_V:
+ case DrmHwcTransform::kFlipV:
rotation = 1 << DRM_REFLECT_Y;
break;
- case HWC_TRANSFORM_ROT_90:
+ case DrmHwcTransform::kRotate90:
rotation = 1 << DRM_ROTATE_90;
break;
- case HWC_TRANSFORM_ROT_180:
+ case DrmHwcTransform::kRotate180:
rotation = 1 << DRM_ROTATE_180;
break;
- case HWC_TRANSFORM_ROT_270:
+ case DrmHwcTransform::kRotate270:
rotation = 1 << DRM_ROTATE_270;
break;
- case 0:
+ case DrmHwcTransform::kIdentity:
rotation = 0;
break;
default:
- ALOGE("Invalid transform value 0x%x given", layer->transform);
+ ALOGE("Invalid transform value 0x%x given", layer.transform);
ret = -EINVAL;
break;
}
@@ -321,27 +314,27 @@
drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
crtc->id()) ||
drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
- iter->bo.fb_id) ||
+ layer.buffer->fb_id) ||
drmModePropertySetAdd(pset, plane->id(), plane->crtc_x_property().id(),
- layer->displayFrame.left) ||
+ layer.display_frame.left) ||
drmModePropertySetAdd(pset, plane->id(), plane->crtc_y_property().id(),
- layer->displayFrame.top) ||
+ layer.display_frame.top) ||
drmModePropertySetAdd(
pset, plane->id(), plane->crtc_w_property().id(),
- layer->displayFrame.right - layer->displayFrame.left) ||
+ layer.display_frame.right - layer.display_frame.left) ||
drmModePropertySetAdd(
pset, plane->id(), plane->crtc_h_property().id(),
- layer->displayFrame.bottom - layer->displayFrame.top) ||
+ layer.display_frame.bottom - layer.display_frame.top) ||
drmModePropertySetAdd(pset, plane->id(), plane->src_x_property().id(),
- (int)(layer->sourceCropf.left) << 16) ||
+ (int)(layer.source_crop.left) << 16) ||
drmModePropertySetAdd(pset, plane->id(), plane->src_y_property().id(),
- (int)(layer->sourceCropf.top) << 16) ||
+ (int)(layer.source_crop.top) << 16) ||
drmModePropertySetAdd(
pset, plane->id(), plane->src_w_property().id(),
- (int)(layer->sourceCropf.right - layer->sourceCropf.left) << 16) ||
+ (int)(layer.source_crop.right - layer.source_crop.left) << 16) ||
drmModePropertySetAdd(
pset, plane->id(), plane->src_h_property().id(),
- (int)(layer->sourceCropf.bottom - layer->sourceCropf.top) << 16);
+ (int)(layer.source_crop.bottom - layer.source_crop.top) << 16);
if (ret) {
ALOGE("Failed to add plane %d to set", plane->id());
break;
@@ -412,6 +405,7 @@
std::unique_ptr<DrmDisplayComposition> composition(
std::move(composite_queue_.front()));
+
composite_queue_.pop();
ret = pthread_mutex_unlock(&lock_);
@@ -474,6 +468,22 @@
return empty_ret;
}
+struct DrmDumpLayer {
+ int plane_id;
+ int crtc_id;
+ DrmHwcTransform transform;
+ DrmHwcRect<float> source_crop;
+ DrmHwcRect<int> display_frame;
+
+ DrmDumpLayer(DrmCompositionLayer &rhs)
+ : plane_id(rhs.plane->id()),
+ crtc_id(rhs.crtc ? rhs.crtc->id() : -1),
+ transform(rhs.transform),
+ source_crop(rhs.source_crop),
+ display_frame(rhs.display_frame) {
+ }
+};
+
void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
uint64_t cur_ts;
@@ -487,9 +497,11 @@
struct timespec ts;
ret = clock_gettime(CLOCK_MONOTONIC, &ts);
- DrmCompositionLayerVector_t layers;
+ std::vector<DrmCompositionLayer> *input_layers =
+ active_composition_->GetCompositionLayers();
+ std::vector<DrmDumpLayer> layers;
if (active_composition_)
- layers = *active_composition_->GetCompositionLayers();
+ layers.insert(layers.begin(), input_layers->begin(), input_layers->end());
else
ret = -EAGAIN;
@@ -508,29 +520,26 @@
dump_last_timestamp_ns_ = cur_ts;
*out << "---- DrmDisplayCompositor Layers: num=" << layers.size() << "\n";
- for (DrmCompositionLayerVector_t::iterator iter = layers.begin();
+ for (std::vector<DrmDumpLayer>::iterator iter = layers.begin();
iter != layers.end(); ++iter) {
- hwc_layer_1_t *layer = &iter->layer;
- DrmPlane *plane = iter->plane;
+ *out << "------ DrmDisplayCompositor Layer: plane=" << iter->plane_id
+ << " ";
- *out << "------ DrmDisplayCompositor Layer: plane=" << plane->id() << " ";
-
- DrmCrtc *crtc = iter->crtc;
- if (!crtc) {
+ if (iter->crtc_id < 0) {
*out << "disabled\n";
continue;
}
- *out << "crtc=" << crtc->id()
- << " crtc[x/y/w/h]=" << layer->displayFrame.left << "/"
- << layer->displayFrame.top << "/"
- << layer->displayFrame.right - layer->displayFrame.left << "/"
- << layer->displayFrame.bottom - layer->displayFrame.top << " "
- << " src[x/y/w/h]=" << layer->sourceCropf.left << "/"
- << layer->sourceCropf.top << "/"
- << layer->sourceCropf.right - layer->sourceCropf.left << "/"
- << layer->sourceCropf.bottom - layer->sourceCropf.top
- << " transform=" << layer->transform << "\n";
+ *out << "crtc=" << iter->crtc_id
+ << " crtc[x/y/w/h]=" << iter->display_frame.left << "/"
+ << iter->display_frame.top << "/"
+ << iter->display_frame.right - iter->display_frame.left << "/"
+ << iter->display_frame.bottom - iter->display_frame.top << " "
+ << " src[x/y/w/h]=" << iter->source_crop.left << "/"
+ << iter->source_crop.top << "/"
+ << iter->source_crop.right - iter->source_crop.left << "/"
+ << iter->source_crop.bottom - iter->source_crop.top
+ << " transform=" << (uint32_t)iter->transform << "\n";
}
}
}
diff --git a/glworker.cpp b/glworker.cpp
index f18ace9..4cbe142 100644
--- a/glworker.cpp
+++ b/glworker.cpp
@@ -33,6 +33,8 @@
#include <utils/Trace.h>
+#include "drmdisplaycomposition.h"
+
#include "glworker.h"
#include "seperate_rects.h"
@@ -184,7 +186,6 @@
"\n"
"precision mediump int; \n"
"uniform vec4 uViewport; \n"
-"uniform sampler2D uLayerTextures[LAYER_COUNT]; \n"
"uniform vec4 uLayerCrop[LAYER_COUNT]; \n"
"uniform mat2 uTexMatrix[LAYER_COUNT]; \n"
"in vec2 vPosition; \n"
@@ -193,8 +194,7 @@
"void main() { \n"
" for (int i = 0; i < LAYER_COUNT; i++) { \n"
" vec2 tempCoords = vTexCoords * uTexMatrix[i]; \n"
-" fTexCoords[i] = (uLayerCrop[i].xy + tempCoords * uLayerCrop[i].zw) / \n"
-" vec2(textureSize(uLayerTextures[i], 0)); \n"
+" fTexCoords[i] = uLayerCrop[i].xy + tempCoords * uLayerCrop[i].zw; \n"
" } \n"
" vec2 scaledPosition = uViewport.xy + vPosition * uViewport.zw; \n"
" gl_Position = vec4(scaledPosition * vec2(2.0) - vec2(1.0), 0.0, 1.0); \n"
@@ -202,8 +202,9 @@
const GLchar *fragment_shader_source =
"\n"
+"#extension GL_OES_EGL_image_external : require \n"
"precision mediump float; \n"
-"uniform sampler2D uLayerTextures[LAYER_COUNT]; \n"
+"uniform samplerExternalOES uLayerTextures[LAYER_COUNT]; \n"
"uniform float uLayerAlpha[LAYER_COUNT]; \n"
"in vec2 fTexCoords[LAYER_COUNT]; \n"
"out vec4 oFragColor; \n"
@@ -211,7 +212,7 @@
" vec3 color = vec3(0.0, 0.0, 0.0); \n"
" float alphaCover = 1.0; \n"
" for (int i = 0; i < LAYER_COUNT; i++) { \n"
-" vec4 texSample = texture(uLayerTextures[i], fTexCoords[i]); \n"
+" vec4 texSample = texture2D(uLayerTextures[i], fTexCoords[i]); \n"
" float a = texSample.a * uLayerAlpha[i]; \n"
" color += a * alphaCover * texSample.rgb; \n"
" alphaCover *= 1.0 - a; \n"
@@ -305,18 +306,15 @@
}
};
-static void ConstructCommands(const hwc_layer_1 *layers, size_t num_layers,
+static void ConstructCommands(DrmCompositionLayer *layers, size_t num_layers,
std::vector<RenderingCommand> *commands) {
std::vector<FRect> in_rects;
std::vector<FRectSet> out_rects;
int i;
for (unsigned rect_index = 0; rect_index < num_layers; rect_index++) {
- const hwc_layer_1 &layer = layers[rect_index];
- FRect rect;
- in_rects.push_back(FRect(layer.displayFrame.left, layer.displayFrame.top,
- layer.displayFrame.right,
- layer.displayFrame.bottom));
+ DrmCompositionLayer &layer = layers[rect_index];
+ in_rects.emplace_back(layer.display_frame);
}
seperate_frects_64(in_rects, &out_rects);
@@ -326,23 +324,28 @@
commands->push_back(RenderingCommand());
RenderingCommand &cmd = commands->back();
- memcpy(cmd.bounds, out_rect.rect.bounds, sizeof(cmd.bounds));
+ for (int i = 0; i < 4; i++)
+ cmd.bounds[i] = out_rect.rect.bounds[i];
uint64_t tex_set = out_rect.id_set.getBits();
for (unsigned i = num_layers - 1; tex_set != 0x0; i--) {
if (tex_set & (0x1 << i)) {
tex_set &= ~(0x1 << i);
- const hwc_layer_1 &layer = layers[i];
+ DrmCompositionLayer &layer = layers[i];
- FRect display_rect(layer.displayFrame.left, layer.displayFrame.top,
- layer.displayFrame.right, layer.displayFrame.bottom);
+ FRect display_rect(layer.display_frame);
float display_size[2] = {
display_rect.bounds[2] - display_rect.bounds[0],
display_rect.bounds[3] - display_rect.bounds[1]};
- FRect crop_rect(layer.sourceCropf.left, layer.sourceCropf.top,
- layer.sourceCropf.right, layer.sourceCropf.bottom);
+ float tex_width = layer.buffer->width;
+ float tex_height = layer.buffer->height;
+ FRect crop_rect(layer.source_crop.left / tex_width,
+ layer.source_crop.top / tex_height,
+ layer.source_crop.right / tex_width,
+ layer.source_crop.bottom / tex_height);
+
float crop_size[2] = {crop_rect.bounds[2] - crop_rect.bounds[0],
crop_rect.bounds[3] - crop_rect.bounds[1]};
@@ -352,27 +355,39 @@
bool swap_xy, flip_xy[2];
switch (layer.transform) {
- case HWC_TRANSFORM_FLIP_H:
- swap_xy = false; flip_xy[0] = true; flip_xy[1] = false;
+ case DrmHwcTransform::kFlipH:
+ swap_xy = false;
+ flip_xy[0] = true;
+ flip_xy[1] = false;
break;
- case HWC_TRANSFORM_FLIP_V:
- swap_xy = false; flip_xy[0] = false; flip_xy[1] = true;
+ case DrmHwcTransform::kFlipV:
+ swap_xy = false;
+ flip_xy[0] = false;
+ flip_xy[1] = true;
break;
- case HWC_TRANSFORM_ROT_90:
- swap_xy = true; flip_xy[0] = false; flip_xy[1] = true;
+ case DrmHwcTransform::kRotate90:
+ swap_xy = true;
+ flip_xy[0] = false;
+ flip_xy[1] = true;
break;
- case HWC_TRANSFORM_ROT_180:
- swap_xy = false; flip_xy[0] = true; flip_xy[1] = true;
+ case DrmHwcTransform::kRotate180:
+ swap_xy = false;
+ flip_xy[0] = true;
+ flip_xy[1] = true;
break;
- case HWC_TRANSFORM_ROT_270:
- swap_xy = true; flip_xy[0] = true; flip_xy[1] = false;
+ case DrmHwcTransform::kRotate270:
+ swap_xy = true;
+ flip_xy[0] = true;
+ flip_xy[1] = false;
break;
default:
ALOGE(
"Unknown transform for layer: defaulting to identity "
"transform");
- case 0:
- swap_xy = false; flip_xy[0] = false; flip_xy[1] = false;
+ case DrmHwcTransform::kIdentity:
+ swap_xy = false;
+ flip_xy[0] = false;
+ flip_xy[1] = false;
break;
}
@@ -394,14 +409,14 @@
}
}
- if (layer.blending == HWC_BLENDING_NONE) {
+ if (layer.blending == DrmHwcBlending::kNone) {
src.alpha = 1.0f;
// This layer is opaque. There is no point in using layers below this
// one.
break;
}
- src.alpha = layer.planeAlpha / 255.0f;
+ src.alpha = layer.alpha / 255.0f;
}
}
}
@@ -444,13 +459,13 @@
GLuint texture;
glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
out->image.reset(egl_display, image);
out->texture.reset(texture);
@@ -539,6 +554,9 @@
if (!HasExtension("GL_OES_EGL_image", gl_extensions))
ALOGW("GL_OES_EGL_image extension not supported");
+ if (!HasExtension("GL_OES_EGL_image_external", gl_extensions))
+ ALOGW("GL_OES_EGL_image_external extension not supported");
+
GLuint vertex_buffer;
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
@@ -559,7 +577,8 @@
ALOGE("Failed to destroy OpenGL ES Context: %s", GetEGLError());
}
-int GLWorkerCompositor::Composite(hwc_layer_1 *layers, size_t num_layers,
+int GLWorkerCompositor::Composite(DrmCompositionLayer *layers,
+ size_t num_layers,
const sp<GraphicBuffer> &framebuffer) {
ATRACE_CALL();
int ret = 0;
@@ -581,23 +600,14 @@
}
for (i = 0; i < num_layers; i++) {
- struct hwc_layer_1 *layer = &layers[i];
-
- if (ret) {
- if (layer->acquireFenceFd >= 0) {
- close(layer->acquireFenceFd);
- layer->acquireFenceFd = -1;
- }
- continue;
- }
+ DrmCompositionLayer *layer = &layers[i];
layer_textures.emplace_back();
- ret = CreateTextureFromHandle(egl_display_, layer->handle,
+ ret = CreateTextureFromHandle(egl_display_, layer->get_usable_handle(),
&layer_textures.back());
if (!ret) {
- ret = EGLFenceWait(egl_display_, layer->acquireFenceFd);
- layer->acquireFenceFd = -1;
+ ret = EGLFenceWait(egl_display_, layer->acquire_fence.Release());
}
if (ret) {
layer_textures.pop_back();
@@ -658,7 +668,7 @@
glUniformMatrix2fv(gl_tex_matrix_loc + src_index, 1, GL_FALSE,
src.texture_matrix);
glActiveTexture(GL_TEXTURE0 + src_index);
- glBindTexture(GL_TEXTURE_2D,
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES,
layer_textures[src.texture_index].texture.get());
}
@@ -668,7 +678,7 @@
for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) {
glActiveTexture(GL_TEXTURE0 + src_index);
- glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
}
}
diff --git a/glworker.h b/glworker.h
index ce41444..b3163ce 100644
--- a/glworker.h
+++ b/glworker.h
@@ -33,13 +33,15 @@
namespace android {
+struct DrmCompositionLayer;
+
class GLWorkerCompositor {
public:
GLWorkerCompositor();
~GLWorkerCompositor();
int Init();
- int Composite(hwc_layer_1 *layers, size_t num_layers,
+ int Composite(DrmCompositionLayer *layers, size_t num_layers,
const sp<GraphicBuffer> &framebuffer);
void Finish();
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 060a955..0a8b661 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -26,6 +26,7 @@
#include <map>
#include <vector>
+#include <sstream>
#include <errno.h>
#include <fcntl.h>
@@ -39,6 +40,8 @@
#include <cutils/properties.h>
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
+#include <sw_sync.h>
+#include <sync/sync.h>
#include <utils/Trace.h>
#define UM_PER_INCH 25400
@@ -46,6 +49,72 @@
namespace android {
+class DummySwSyncTimeline {
+ public:
+ int Init() {
+ int ret = timeline_fd_.Set(sw_sync_timeline_create());
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
+
+ UniqueFd CreateDummyFence() {
+ int ret = sw_sync_fence_create(timeline_fd_.get(), "dummy fence",
+ timeline_pt_ + 1);
+ if (ret < 0) {
+ ALOGE("Failed to create dummy fence %d", ret);
+ return ret;
+ }
+
+ UniqueFd ret_fd(ret);
+
+ ret = sw_sync_timeline_inc(timeline_fd_.get(), 1);
+ if (ret) {
+ ALOGE("Failed to increment dummy sync timeline %d", ret);
+ return ret;
+ }
+
+ ++timeline_pt_;
+ return ret_fd;
+ }
+
+ private:
+ UniqueFd timeline_fd_;
+ int timeline_pt_ = 0;
+};
+
+struct CheckedOutputFd {
+ CheckedOutputFd(int *fd, const char *description,
+ DummySwSyncTimeline &timeline)
+ : fd_(fd), description_(description), timeline_(timeline) {
+ }
+ CheckedOutputFd(CheckedOutputFd &&rhs)
+ : description_(rhs.description_), timeline_(rhs.timeline_) {
+ std::swap(fd_, rhs.fd_);
+ }
+
+ CheckedOutputFd &operator=(const CheckedOutputFd &rhs) = delete;
+
+ ~CheckedOutputFd() {
+ if (fd_ == NULL)
+ return;
+
+ if (*fd_ >= 0)
+ return;
+
+ *fd_ = timeline_.CreateDummyFence().Release();
+
+ if (*fd_ < 0)
+ ALOGE("Failed to fill %s (%p == %d) before destruction",
+ description_.c_str(), fd_, *fd_);
+ }
+
+ private:
+ int *fd_ = NULL;
+ std::string description_;
+ DummySwSyncTimeline &timeline_;
+};
+
typedef struct hwc_drm_display {
struct hwc_context_t *ctx;
int display;
@@ -73,9 +142,184 @@
DisplayMap displays;
DrmResources drm;
Importer *importer;
+ const gralloc_module_t *gralloc;
+ DummySwSyncTimeline dummy_timeline;
bool use_framebuffer_target;
};
+static native_handle_t *dup_buffer_handle(buffer_handle_t handle) {
+ native_handle_t *new_handle =
+ native_handle_create(handle->numFds, handle->numInts);
+ if (new_handle == NULL)
+ return NULL;
+
+ const int *old_data = handle->data;
+ int *new_data = new_handle->data;
+ for (int i = 0; i < handle->numFds; i++) {
+ *new_data = dup(*old_data);
+ old_data++;
+ new_data++;
+ }
+ memcpy(new_data, old_data, sizeof(int) * handle->numInts);
+
+ return new_handle;
+}
+
+static void free_buffer_handle(native_handle_t *handle) {
+ int ret = native_handle_close(handle);
+ if (ret)
+ ALOGE("Failed to close native handle %d", ret);
+ ret = native_handle_delete(handle);
+ if (ret)
+ ALOGE("Failed to delete native handle %d", ret);
+}
+
+OutputFd &OutputFd::operator=(OutputFd &&rhs) {
+ if (fd_ == NULL) {
+ std::swap(fd_, rhs.fd_);
+ } else {
+ if (*fd_ < 0) {
+ ALOGE("Failed to fill OutputFd %p before assignment", fd_);
+ }
+ fd_ = rhs.fd_;
+ rhs.fd_ = NULL;
+ }
+
+ return *this;
+}
+
+hwc_drm_bo *DrmHwcBuffer::operator->() {
+ if (importer_ == NULL) {
+ ALOGE("Access of none existent BO");
+ exit(1);
+ return NULL;
+ }
+ return &bo_;
+}
+
+void DrmHwcBuffer::Clear() {
+ if (importer_ != NULL) {
+ importer_->ReleaseBuffer(&bo_);
+ importer_ = NULL;
+ }
+}
+
+int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) {
+ hwc_drm_bo tmp_bo;
+
+ int ret = importer->ImportBuffer(handle, &tmp_bo);
+ if (ret)
+ return ret;
+
+ if (importer_ != NULL) {
+ importer_->ReleaseBuffer(&bo_);
+ }
+
+ importer_ = importer;
+
+ bo_ = tmp_bo;
+
+ return 0;
+}
+
+int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle,
+ const gralloc_module_t *gralloc) {
+ native_handle_t *handle_copy = dup_buffer_handle(handle);
+ if (handle_copy == NULL) {
+ ALOGE("Failed to duplicate handle");
+ return -ENOMEM;
+ }
+
+ int ret = gralloc->registerBuffer(gralloc, handle_copy);
+ if (ret) {
+ ALOGE("Failed to register buffer handle %d", ret);
+ free_buffer_handle(handle_copy);
+ return ret;
+ }
+
+ Clear();
+
+ gralloc_ = gralloc;
+ handle_ = handle_copy;
+
+ return 0;
+}
+
+DrmHwcNativeHandle::~DrmHwcNativeHandle() {
+ Clear();
+}
+
+void DrmHwcNativeHandle::Clear() {
+ if (gralloc_ != NULL && handle_ != NULL) {
+ gralloc_->unregisterBuffer(gralloc_, handle_);
+ free_buffer_handle(handle_);
+ gralloc_ = NULL;
+ handle_ = NULL;
+ }
+}
+
+int DrmHwcLayer::InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
+ const gralloc_module_t *gralloc) {
+ sf_handle = sf_layer->handle;
+ int ret = buffer.ImportBuffer(sf_layer->handle, importer);
+ if (ret)
+ return ret;
+
+ ret = handle.CopyBufferHandle(sf_layer->handle, gralloc);
+ if (ret)
+ return ret;
+
+ alpha = sf_layer->planeAlpha;
+
+ switch (sf_layer->transform) {
+ case 0:
+ transform = DrmHwcTransform::kIdentity;
+ break;
+ case HWC_TRANSFORM_FLIP_H:
+ transform = DrmHwcTransform::kFlipH;
+ break;
+ case HWC_TRANSFORM_FLIP_V:
+ transform = DrmHwcTransform::kFlipV;
+ break;
+ case HWC_TRANSFORM_ROT_90:
+ transform = DrmHwcTransform::kRotate90;
+ break;
+ case HWC_TRANSFORM_ROT_180:
+ transform = DrmHwcTransform::kRotate180;
+ break;
+ case HWC_TRANSFORM_ROT_270:
+ transform = DrmHwcTransform::kRotate270;
+ break;
+ default:
+ ALOGE("Invalid transform in hwc_layer_1_t %d", sf_layer->transform);
+ return -EINVAL;
+ }
+
+ switch (sf_layer->blending) {
+ case HWC_BLENDING_NONE:
+ blending = DrmHwcBlending::kNone;
+ break;
+ case HWC_BLENDING_PREMULT:
+ blending = DrmHwcBlending::kPreMult;
+ break;
+ case HWC_BLENDING_COVERAGE:
+ blending = DrmHwcBlending::kCoverage;
+ break;
+ default:
+ ALOGE("Invalid blending in hwc_layer_1_t %d", sf_layer->blending);
+ return -EINVAL;
+ }
+
+ source_crop = DrmHwcRect<float>(
+ sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
+ sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom);
+ display_frame = DrmHwcRect<int>(
+ sf_layer->displayFrame.left, sf_layer->displayFrame.top,
+ sf_layer->displayFrame.right, sf_layer->displayFrame.bottom);
+
+ return 0;
+}
+
static void hwc_dump(struct hwc_composer_device_1 *dev, char *buff,
int buff_len) {
struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
@@ -131,27 +375,6 @@
return 0;
}
-static void hwc_set_cleanup(size_t num_displays,
- hwc_display_contents_1_t **display_contents) {
- for (int i = 0; i < (int)num_displays; ++i) {
- if (!display_contents[i])
- continue;
-
- hwc_display_contents_1_t *dc = display_contents[i];
- for (size_t j = 0; j < dc->numHwLayers; ++j) {
- hwc_layer_1_t *layer = &dc->hwLayers[j];
- if (layer->acquireFenceFd >= 0) {
- close(layer->acquireFenceFd);
- layer->acquireFenceFd = -1;
- }
- }
- if (dc->outbufAcquireFenceFd >= 0) {
- close(dc->outbufAcquireFenceFd);
- dc->outbufAcquireFenceFd = -1;
- }
- }
-}
-
static void hwc_add_layer_to_retire_fence(
hwc_layer_1_t *layer, hwc_display_contents_1_t *display_contents) {
if (layer->releaseFenceFd < 0)
@@ -168,109 +391,133 @@
}
static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
- hwc_display_contents_1_t **display_contents) {
+ hwc_display_contents_1_t **sf_display_contents) {
ATRACE_CALL();
struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
- int ret;
- std::unique_ptr<DrmComposition> composition(
- ctx->drm.compositor()->CreateComposition(ctx->importer));
- if (!composition) {
- ALOGE("Drm composition init failed");
- hwc_set_cleanup(num_displays, display_contents);
- return -EINVAL;
- }
+ int ret = 0;
+ std::vector<CheckedOutputFd> checked_output_fences;
+ std::vector<DrmHwcDisplayContents> displays_contents;
std::vector<DrmCompositionDisplayLayersMap> layers_map;
std::vector<std::vector<size_t>> layers_indices;
- layers_map.reserve(num_displays);
+ displays_contents.reserve(num_displays);
+ // layers_map.reserve(num_displays);
layers_indices.reserve(num_displays);
- for (int i = 0; i < (int)num_displays; ++i) {
- if (!display_contents[i])
+ // Phase one does nothing that would cause errors. Only take ownership of FDs.
+ for (size_t i = 0; i < num_displays; ++i) {
+ hwc_display_contents_1_t *dc = sf_display_contents[i];
+ displays_contents.emplace_back();
+ DrmHwcDisplayContents &display_contents = displays_contents.back();
+
+ if (!sf_display_contents[i])
continue;
- hwc_display_contents_1_t *dc = display_contents[i];
- layers_map.emplace_back();
- DrmCompositionDisplayLayersMap &map = layers_map[i];
- map.display = i;
- map.layers = dc->hwLayers;
+ std::ostringstream display_index_formatter;
+ display_index_formatter << "retire fence for display " << i;
+ std::string display_fence_description(display_index_formatter.str());
+ checked_output_fences.emplace_back(&dc->retireFenceFd,
+ display_fence_description.c_str(),
+ ctx->dummy_timeline);
+ display_contents.retire_fence = OutputFd(&dc->retireFenceFd);
+ size_t num_dc_layers = dc->numHwLayers;
std::vector<size_t> indices_to_composite;
- unsigned num_dc_layers = dc->numHwLayers;
int framebuffer_target_index = -1;
- for (int j = 0; j < (int)num_dc_layers; ++j) {
- hwc_layer_1_t *layer = &dc->hwLayers[j];
- if (layer->flags & HWC_SKIP_LAYER)
+ for (size_t j = 0; j < num_dc_layers; ++j) {
+ hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
+
+ display_contents.layers.emplace_back();
+ DrmHwcLayer &layer = display_contents.layers.back();
+
+ if (sf_layer->flags & HWC_SKIP_LAYER)
continue;
+
if (!ctx->use_framebuffer_target) {
- if (layer->compositionType == HWC_OVERLAY)
+ if (sf_layer->compositionType == HWC_OVERLAY)
indices_to_composite.push_back(j);
- if (layer->compositionType == HWC_FRAMEBUFFER_TARGET)
+ if (sf_layer->compositionType == HWC_FRAMEBUFFER_TARGET)
framebuffer_target_index = j;
} else {
- if (layer->compositionType == HWC_FRAMEBUFFER_TARGET)
+ if (sf_layer->compositionType == HWC_FRAMEBUFFER_TARGET)
indices_to_composite.push_back(j);
}
+
+ layer.acquire_fence.Set(sf_layer->acquireFenceFd);
+ sf_layer->acquireFenceFd = -1;
+
+ std::ostringstream layer_fence_formatter;
+ layer_fence_formatter << "release fence for layer " << j << " of display "
+ << i;
+ std::string layer_fence_description(layer_fence_formatter.str());
+ checked_output_fences.emplace_back(&sf_layer->releaseFenceFd,
+ layer_fence_description.c_str(),
+ ctx->dummy_timeline);
+ layer.release_fence = OutputFd(&sf_layer->releaseFenceFd);
}
+
if (ctx->use_framebuffer_target) {
if (indices_to_composite.size() != 1) {
ALOGE("Expected 1 (got %d) layer with HWC_FRAMEBUFFER_TARGET",
indices_to_composite.size());
- hwc_set_cleanup(num_displays, display_contents);
- return -EINVAL;
+ ret = -EINVAL;
}
} else {
if (indices_to_composite.empty() && framebuffer_target_index >= 0) {
- // Fall back to use HWC_FRAMEBUFFER_TARGET if all HWC_OVERLAY layers
- // are skipped.
- hwc_layer_1_t *layer = &dc->hwLayers[framebuffer_target_index];
- if (!layer->handle || (layer->flags & HWC_SKIP_LAYER)) {
- ALOGE("Expected valid layer with HWC_FRAMEBUFFER_TARGET when all "
- "HWC_OVERLAY layers are skipped.");
- hwc_set_cleanup(num_displays, display_contents);
- return -EINVAL;
+ hwc_layer_1_t *sf_layer = &dc->hwLayers[framebuffer_target_index];
+ if (!sf_layer->handle || (sf_layer->flags & HWC_SKIP_LAYER)) {
+ ALOGE(
+ "Expected valid layer with HWC_FRAMEBUFFER_TARGET when all "
+ "HWC_OVERLAY layers are skipped.");
+ ret = -EINVAL;
}
indices_to_composite.push_back(framebuffer_target_index);
}
}
+ layers_indices.emplace_back(indices_to_composite);
+ }
- map.num_layers = indices_to_composite.size();
- layers_indices.emplace_back(std::move(indices_to_composite));
- map.layer_indices = layers_indices.back().data();
+ if (ret)
+ return ret;
+
+ for (size_t i = 0; i < num_displays; ++i) {
+ hwc_display_contents_1_t *dc = sf_display_contents[i];
+ DrmHwcDisplayContents &display_contents = displays_contents[i];
+ if (!sf_display_contents[i])
+ continue;
+
+ layers_map.emplace_back();
+ DrmCompositionDisplayLayersMap &map = layers_map.back();
+ std::vector<size_t> &indices_to_composite = layers_indices[i];
+ for (size_t j : indices_to_composite) {
+ hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
+
+ DrmHwcLayer &layer = display_contents.layers[j];
+
+ layer.InitFromHwcLayer(sf_layer, ctx->importer, ctx->gralloc);
+ map.layers.emplace_back(std::move(layer));
+ }
+ }
+
+ std::unique_ptr<DrmComposition> composition(
+ ctx->drm.compositor()->CreateComposition(ctx->importer));
+ if (!composition) {
+ ALOGE("Drm composition init failed");
+ return -EINVAL;
}
ret = composition->SetLayers(layers_map.size(), layers_map.data());
if (ret) {
- hwc_set_cleanup(num_displays, display_contents);
return -EINVAL;
}
ret = ctx->drm.compositor()->QueueComposition(std::move(composition));
if (ret) {
- hwc_set_cleanup(num_displays, display_contents);
return -EINVAL;
}
composition.reset(NULL);
- for (int i = 0; i < (int)num_displays; ++i) {
- if (!display_contents[i])
- continue;
- hwc_display_contents_1_t *dc = display_contents[i];
- unsigned num_dc_layers = dc->numHwLayers;
- for (int j = 0; j < (int)num_dc_layers; ++j) {
- hwc_layer_1_t *layer = &dc->hwLayers[j];
- if (layer->flags & HWC_SKIP_LAYER)
- continue;
- if (layer->compositionType == HWC_OVERLAY)
- hwc_add_layer_to_retire_fence(layer, dc);
- }
- }
-
- if (ret) {
- ALOGE("Failed to queue the composition");
- }
- hwc_set_cleanup(num_displays, display_contents);
return ret;
}
@@ -551,6 +798,20 @@
return ret;
}
+ ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&ctx->gralloc);
+ if (ret) {
+ ALOGE("Failed to open gralloc module %d", ret);
+ delete ctx;
+ return ret;
+ }
+
+ ret = ctx->dummy_timeline.Init();
+ if (ret) {
+ ALOGE("Failed to create dummy sw sync timeline %d", ret);
+ return ret;
+ }
+
ctx->importer = Importer::CreateInstance(&ctx->drm);
if (!ctx->importer) {
ALOGE("Failed to create importer instance");
diff --git a/seperate_rects.h b/seperate_rects.h
index 9bf95a3..540a5e8 100644
--- a/seperate_rects.h
+++ b/seperate_rects.h
@@ -43,11 +43,19 @@
: x1(xx1), y1(yy1), x2(xx2), y2(yy2) {
}
- Rect(const Rect &rhs) {
+ template <typename T>
+ Rect(const Rect<T> &rhs) {
for (int i = 0; i < 4; i++)
bounds[i] = rhs.bounds[i];
}
+ template <typename T>
+ Rect<TFloat> &operator=(const Rect<T> &rhs) {
+ for (int i = 0; i < 4; i++)
+ bounds[i] = rhs.bounds[i];
+ return *this;
+ }
+
bool operator==(const Rect &rhs) const {
for (int i = 0; i < 4; i++) {
if (bounds[i] != rhs.bounds[i])