aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autogl.h110
-rw-r--r--drmcomposition.cpp58
-rw-r--r--drmcomposition.h18
-rw-r--r--drmcompositor.cpp4
-rw-r--r--drmcompositor.h3
-rw-r--r--drmdisplaycomposition.cpp243
-rw-r--r--drmdisplaycomposition.h24
-rw-r--r--drmdisplaycompositor.cpp68
-rw-r--r--drmresources.cpp7
-rw-r--r--glworker.cpp15
-rw-r--r--glworker.h46
-rw-r--r--hwcomposer.cpp112
12 files changed, 432 insertions, 276 deletions
diff --git a/autogl.h b/autogl.h
new file mode 100644
index 0000000..5d25e44
--- /dev/null
+++ b/autogl.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUTO_GL_H_
+#define ANDROID_AUTO_GL_H_
+
+#include <memory>
+#define EGL_EGLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+// TODO(zachr): use hwc_drm_bo to turn buffer handles into textures
+#ifndef EGL_NATIVE_HANDLE_ANDROID_NVX
+#define EGL_NATIVE_HANDLE_ANDROID_NVX 0x322A
+#endif
+
+namespace android {
+
+#define AUTO_GL_TYPE(name, type, zero, deleter) \
+ struct name##Deleter { \
+ typedef type pointer; \
+ \
+ void operator()(pointer p) const { \
+ if (p != zero) { \
+ deleter; \
+ } \
+ } \
+ }; \
+ typedef std::unique_ptr<type, name##Deleter> name;
+
+AUTO_GL_TYPE(AutoGLFramebuffer, GLuint, 0, glDeleteFramebuffers(1, &p))
+AUTO_GL_TYPE(AutoGLBuffer, GLuint, 0, glDeleteBuffers(1, &p))
+AUTO_GL_TYPE(AutoGLTexture, GLuint, 0, glDeleteTextures(1, &p))
+AUTO_GL_TYPE(AutoGLShader, GLint, 0, glDeleteShader(p))
+AUTO_GL_TYPE(AutoGLProgram, GLint, 0, glDeleteProgram(p))
+
+struct AutoEGLDisplayImage {
+ AutoEGLDisplayImage() : display_(EGL_NO_DISPLAY), image_(EGL_NO_IMAGE_KHR) {
+ }
+
+ AutoEGLDisplayImage(EGLDisplay display, EGLImageKHR image)
+ : display_(display), image_(image) {
+ }
+
+ AutoEGLDisplayImage(const AutoEGLDisplayImage& rhs) = delete;
+ AutoEGLDisplayImage(AutoEGLDisplayImage&& rhs) {
+ clear();
+ std::swap(display_, rhs.display_);
+ std::swap(image_, rhs.image_);
+ }
+
+ ~AutoEGLDisplayImage() {
+ clear();
+ }
+
+ AutoEGLDisplayImage& operator=(const AutoEGLDisplayImage& rhs) = delete;
+ AutoEGLDisplayImage& operator=(AutoEGLDisplayImage&& rhs) {
+ clear();
+ std::swap(display_, rhs.display_);
+ std::swap(image_, rhs.image_);
+ return *this;
+ }
+
+ void reset(EGLDisplay display, EGLImageKHR image) {
+ clear();
+ display_ = display;
+ image_ = image;
+ }
+
+ void clear() {
+ if (image_ != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(display_, image_);
+ display_ = EGL_NO_DISPLAY;
+ image_ = EGL_NO_IMAGE_KHR;
+ }
+ }
+
+ EGLImageKHR image() const {
+ return image_;
+ }
+
+ private:
+ EGLDisplay display_;
+ EGLImageKHR image_;
+};
+
+struct AutoEGLImageAndGLTexture {
+ AutoEGLDisplayImage image;
+ AutoGLTexture texture;
+};
+}
+
+#endif
diff --git a/drmcomposition.cpp b/drmcomposition.cpp
index f4e8d9d..0c0f394 100644
--- a/drmcomposition.cpp
+++ b/drmcomposition.cpp
@@ -42,9 +42,6 @@ DrmComposition::DrmComposition(DrmResources *drm, Importer *importer)
}
}
-DrmComposition::~DrmComposition() {
-}
-
int DrmComposition::Init() {
for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
iter != drm_->end_connectors(); ++iter) {
@@ -54,7 +51,12 @@ int DrmComposition::Init() {
ALOGE("Failed to allocate new display composition\n");
return -ENOMEM;
}
- int ret = composition_map_[(*iter)->display()]->Init(drm_, importer_);
+ DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
+ if (!crtc) {
+ ALOGE("Failed to find crtc for display %d", display);
+ return -ENODEV;
+ }
+ int ret = composition_map_[(*iter)->display()]->Init(drm_, crtc, importer_);
if (ret) {
ALOGE("Failed to init display composition for %d", (*iter)->display());
return ret;
@@ -63,42 +65,26 @@ int DrmComposition::Init() {
return 0;
}
-unsigned DrmComposition::GetRemainingLayers(int /*display*/,
- unsigned num_needed) const {
- return num_needed;
-}
-
-int DrmComposition::AddLayer(int display, hwc_layer_1_t *layer,
- hwc_drm_bo *bo) {
- DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
- if (!crtc) {
- ALOGE("Failed to find crtc for display %d", display);
- return -ENODEV;
+int DrmComposition::SetLayers(size_t num_displays,
+ const DrmCompositionDisplayLayersMap *maps) {
+ int ret = 0;
+ for (size_t display_index = 0; display_index < num_displays;
+ display_index++) {
+ const DrmCompositionDisplayLayersMap &map = maps[display_index];
+ int display = map.display;
+
+ ret = composition_map_[display]->SetLayers(
+ map.layers, map.num_layers, map.layer_indices, &primary_planes_,
+ &overlay_planes_);
+ if (ret)
+ return ret;
}
- // Find a plane for the layer
- DrmPlane *plane = NULL;
- for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
- iter != primary_planes_.end(); ++iter) {
- if ((*iter)->GetCrtcSupported(*crtc)) {
- plane = *iter;
- primary_planes_.erase(iter);
- break;
- }
- }
- for (std::vector<DrmPlane *>::iterator iter = overlay_planes_.begin();
- !plane && iter != overlay_planes_.end(); ++iter) {
- if ((*iter)->GetCrtcSupported(*crtc)) {
- plane = *iter;
- overlay_planes_.erase(iter);
- break;
- }
- }
- return composition_map_[display]->AddLayer(layer, bo, crtc, plane);
+ return DisableUnusedPlanes();
}
-int DrmComposition::AddDpmsMode(int display, uint32_t dpms_mode) {
- return composition_map_[display]->AddDpmsMode(dpms_mode);
+int DrmComposition::SetDpmsMode(int display, uint32_t dpms_mode) {
+ return composition_map_[display]->SetDpmsMode(dpms_mode);
}
std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition(
diff --git a/drmcomposition.h b/drmcomposition.h
index 69bf6d9..ee2e258 100644
--- a/drmcomposition.h
+++ b/drmcomposition.h
@@ -31,21 +31,26 @@
namespace android {
+struct DrmCompositionDisplayLayersMap {
+ int display;
+ size_t num_layers;
+ hwc_layer_1_t *layers;
+ size_t *layer_indices;
+};
+
class DrmComposition {
public:
DrmComposition(DrmResources *drm, Importer *importer);
- ~DrmComposition();
int Init();
- unsigned GetRemainingLayers(int display, unsigned num_needed) const;
- int AddLayer(int display, hwc_layer_1_t *layer, hwc_drm_bo_t *bo);
- int AddDpmsMode(int display, uint32_t dpms_mode);
-
- int DisableUnusedPlanes();
+ int SetLayers(size_t num_displays,
+ const DrmCompositionDisplayLayersMap *maps);
+ int SetDpmsMode(int display, uint32_t dpms_mode);
std::unique_ptr<DrmDisplayComposition> TakeDisplayComposition(int display);
DrmDisplayComposition *GetDisplayComposition(int display);
+ int DisableUnusedPlanes();
private:
DrmComposition(const DrmComposition &) = delete;
@@ -62,7 +67,6 @@ class DrmComposition {
*/
std::map<int, std::unique_ptr<DrmDisplayComposition>> composition_map_;
};
-
}
#endif // ANDROID_DRM_COMPOSITION_H_
diff --git a/drmcompositor.cpp b/drmcompositor.cpp
index 082e75d..c61e60c 100644
--- a/drmcompositor.cpp
+++ b/drmcompositor.cpp
@@ -62,7 +62,8 @@ DrmComposition *DrmCompositor::CreateComposition(Importer *importer) {
return composition;
}
-int DrmCompositor::QueueComposition(DrmComposition *composition) {
+int DrmCompositor::QueueComposition(
+ std::unique_ptr<DrmComposition> composition) {
int ret = composition->DisableUnusedPlanes();
if (ret) {
ALOGE("Failed to disable unused planes %d", ret);
@@ -76,7 +77,6 @@ int DrmCompositor::QueueComposition(DrmComposition *composition) {
composition->TakeDisplayComposition(display));
if (ret) {
ALOGE("Failed to queue composition for display %d", display);
- delete composition;
return ret;
}
}
diff --git a/drmcompositor.h b/drmcompositor.h
index aa4a876..3fc2bb1 100644
--- a/drmcompositor.h
+++ b/drmcompositor.h
@@ -22,6 +22,7 @@
#include "importer.h"
#include <map>
+#include <memory>
#include <sstream>
namespace android {
@@ -35,7 +36,7 @@ class DrmCompositor {
DrmComposition *CreateComposition(Importer *importer);
- int QueueComposition(DrmComposition *composition);
+ int QueueComposition(std::unique_ptr<DrmComposition> composition);
int Composite();
void Dump(std::ostringstream *out) const;
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index d29b957..c7168c0 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -60,13 +60,11 @@ static void free_buffer_handle(native_handle_t *handle) {
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() {
-}
-
DrmDisplayComposition::DrmDisplayComposition()
: drm_(NULL),
importer_(NULL),
@@ -74,6 +72,8 @@ DrmDisplayComposition::DrmDisplayComposition()
timeline_fd_(-1),
timeline_(0),
timeline_current_(0),
+ timeline_pre_comp_done_(0),
+ pre_composition_layer_index_(-1),
dpms_mode_(DRM_MODE_DPMS_ON) {
}
@@ -99,8 +99,10 @@ DrmDisplayComposition::~DrmDisplayComposition() {
}
}
-int DrmDisplayComposition::Init(DrmResources *drm, Importer *importer) {
+int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
+ Importer *importer) {
drm_ = drm;
+ crtc_ = crtc;
importer_ = importer;
int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
@@ -127,69 +129,190 @@ bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
}
-int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, hwc_drm_bo_t *bo,
- DrmCrtc *crtc, DrmPlane *plane) {
+static DrmPlane *TakePlane(DrmCrtc *crtc, std::vector<DrmPlane *> *planes) {
+ for (auto iter = planes->begin(); iter != planes->end(); ++iter) {
+ if ((*iter)->GetCrtcSupported(*crtc)) {
+ DrmPlane *plane = *iter;
+ planes->erase(iter);
+ return plane;
+ }
+ }
+ return NULL;
+}
+
+static DrmPlane *TakePlane(DrmCrtc *crtc,
+ std::vector<DrmPlane *> *primary_planes,
+ std::vector<DrmPlane *> *overlay_planes) {
+ DrmPlane *plane = TakePlane(crtc, primary_planes);
+ if (plane)
+ return plane;
+ return TakePlane(crtc, overlay_planes);
+}
+
+int DrmDisplayComposition::CreateNextTimelineFence() {
+ ++timeline_;
+ return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
+}
+
+int DrmDisplayComposition::IncreaseTimelineToPoint(int point) {
+ int timeline_increase = point - timeline_current_;
+ if (timeline_increase <= 0)
+ return 0;
+
+ int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
+ if (ret)
+ ALOGE("Failed to increment sync timeline %d", ret);
+ else
+ timeline_current_ = point;
+
+ return ret;
+}
+
+int DrmDisplayComposition::SetLayers(hwc_layer_1_t *layers, size_t num_layers,
+ size_t *layer_indices,
+ std::vector<DrmPlane *> *primary_planes,
+ std::vector<DrmPlane *> *overlay_planes) {
+ int ret = 0;
if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
return -EINVAL;
- native_handle_t *handle_copy = dup_buffer_handle(layer->handle);
- if (handle_copy == NULL) {
- ALOGE("Failed to duplicate handle");
- return -ENOMEM;
- }
+ for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
+ hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
+ if (layer->transform != 0)
+ return -EINVAL;
- int ret = gralloc_->registerBuffer(gralloc_, handle_copy);
- if (ret) {
- ALOGE("Failed to register buffer handle %d", ret);
- free_buffer_handle(handle_copy);
- return ret;
+ 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;
+ }
+
+ if (pre_composition_layer_index_ == -1) {
+ c_layer->plane = TakePlane(crtc_, primary_planes, overlay_planes);
+ if (c_layer->plane == NULL) {
+ if (layers_.size() <= 1) {
+ ALOGE("Failed to match any planes to the crtc of this display");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ 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();
+ 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];
+ 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();
+ if (ret < 0) {
+ ALOGE("Could not create release fence %d", ret);
+ goto fail;
+ }
+ }
+ }
+
+ 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();
+ if (ret < 0) {
+ ALOGE("Could not create release fence %d", ret);
+ goto fail;
+ }
+ }
}
- ++timeline_;
- layer->releaseFenceFd =
- sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
- if (layer->releaseFenceFd < 0) {
- free_buffer_handle(handle_copy);
- ALOGE("Could not create release fence %d", layer->releaseFenceFd);
- return layer->releaseFenceFd;
+ 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)
+ continue;
+
+ ret = layer->releaseFenceFd = CreateNextTimelineFence();
+ if (ret < 0) {
+ ALOGE("Could not create release fence %d", ret);
+ goto fail;
+ }
}
- DrmCompositionLayer_t c_layer;
- c_layer.layer = *layer;
- c_layer.bo = *bo;
- c_layer.crtc = crtc;
- c_layer.plane = plane;
- c_layer.handle = handle_copy;
+ 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
+ }
- layer->acquireFenceFd = -1; // We own this now
- layers_.push_back(c_layer);
type_ = DRM_COMPOSITION_TYPE_FRAME;
return 0;
-}
-int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, DrmCrtc *crtc,
- DrmPlane *plane) {
- if (layer->transform != 0)
- return -EINVAL;
-
- if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
- return -EINVAL;
+fail:
- hwc_drm_bo_t bo;
- int ret = importer_->ImportBuffer(layer->handle, &bo);
- if (ret) {
- ALOGE("Failed to import handle of layer %d", ret);
- return ret;
+ 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);
+ if (c_layer.plane != NULL) {
+ std::vector<DrmPlane *> *return_to =
+ (c_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY) ? primary_planes
+ : overlay_planes;
+ return_to->insert(return_to->begin() + c_layer_index, c_layer.plane);
+ }
}
+ layers_.clear();
- ret = AddLayer(layer, &bo, crtc, plane);
- if (ret)
- importer_->ReleaseBuffer(&bo);
+ 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_;
return ret;
}
-int DrmDisplayComposition::AddDpmsMode(uint32_t dpms_mode) {
+int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) {
if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
return -EINVAL;
dpms_mode_ = dpms_mode;
@@ -198,10 +321,10 @@ int DrmDisplayComposition::AddDpmsMode(uint32_t dpms_mode) {
}
int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
- DrmCompositionLayer_t c_layer;
+ layers_.emplace_back();
+ DrmCompositionLayer_t &c_layer = layers_.back();
c_layer.crtc = NULL;
c_layer.plane = plane;
- layers_.push_back(c_layer);
return 0;
}
@@ -231,24 +354,22 @@ void DrmDisplayComposition::RemoveNoPlaneLayers() {
layers_.end());
}
-int DrmDisplayComposition::FinishComposition() {
- int timeline_increase = timeline_ - timeline_current_;
- if (timeline_increase <= 0)
- return 0;
-
- int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
- if (ret)
- ALOGE("Failed to increment sync timeline %d", ret);
- else
- timeline_current_ = timeline_;
+int DrmDisplayComposition::SignalPreCompositionDone() {
+ return IncreaseTimelineToPoint(timeline_pre_comp_done_);
+}
- return ret;
+int DrmDisplayComposition::FinishComposition() {
+ return IncreaseTimelineToPoint(timeline_);
}
DrmCompositionLayerVector_t *DrmDisplayComposition::GetCompositionLayers() {
return &layers_;
}
+int DrmDisplayComposition::pre_composition_layer_index() const {
+ return pre_composition_layer_index_;
+}
+
uint32_t DrmDisplayComposition::dpms_mode() const {
return dpms_mode_;
}
diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h
index 76da993..4d4f2df 100644
--- a/drmdisplaycomposition.h
+++ b/drmdisplaycomposition.h
@@ -18,7 +18,9 @@
#define ANDROID_DRM_DISPLAY_COMPOSITION_H_
#include "drm_hwcomposer.h"
+#include "drmcrtc.h"
#include "drmplane.h"
+#include "glworker.h"
#include "importer.h"
#include <vector>
@@ -37,7 +39,6 @@ enum DrmCompositionType {
typedef struct DrmCompositionLayer {
DrmCompositionLayer();
- ~DrmCompositionLayer();
hwc_layer_1_t layer;
hwc_drm_bo_t bo;
@@ -52,22 +53,22 @@ class DrmDisplayComposition {
DrmDisplayComposition();
~DrmDisplayComposition();
- int Init(DrmResources *drm, Importer *importer);
+ int Init(DrmResources *drm, DrmCrtc *crtc, Importer *importer);
DrmCompositionType type() const;
- int AddLayer(hwc_layer_1_t *layer, hwc_drm_bo_t *bo, DrmCrtc *crtc,
- DrmPlane *plane);
- // Like the AddLayer that accepts a hwc_drm_bo_t, but uses Importer to import
- // the layer->handle itself.
- int AddLayer(hwc_layer_1_t *layer, DrmCrtc *crtc, DrmPlane *plane);
+ int SetLayers(hwc_layer_1_t *layers, size_t num_layers, size_t *layer_indices,
+ std::vector<DrmPlane *> *primary_planes,
+ std::vector<DrmPlane *> *overlay_planes);
int AddPlaneDisable(DrmPlane *plane);
- int AddDpmsMode(uint32_t dpms_mode);
+ int SetDpmsMode(uint32_t dpms_mode);
void RemoveNoPlaneLayers();
+ int SignalPreCompositionDone();
int FinishComposition();
DrmCompositionLayerVector_t *GetCompositionLayers();
+ int pre_composition_layer_index() const;
uint32_t dpms_mode() const;
Importer *importer() const;
@@ -77,17 +78,24 @@ class DrmDisplayComposition {
bool validate_composition_type(DrmCompositionType desired);
+ int CreateNextTimelineFence();
+ int IncreaseTimelineToPoint(int point);
+
DrmResources *drm_;
+ DrmCrtc *crtc_;
Importer *importer_;
const gralloc_module_t *gralloc_;
+ EGLDisplay egl_display_;
DrmCompositionType type_;
int timeline_fd_;
int timeline_;
int timeline_current_;
+ int timeline_pre_comp_done_;
DrmCompositionLayerVector_t layers_;
+ int pre_composition_layer_index_;
uint32_t dpms_mode_;
};
}
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index 1e02e73..7259d07 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -154,17 +154,6 @@ int DrmDisplayCompositor::ApplyPreComposite(
int ret = 0;
DrmCompositionLayerVector_t *layers = display_comp->GetCompositionLayers();
- auto last_layer = find_if(layers->rbegin(), layers->rend(),
- drm_composition_layer_has_plane);
- if (last_layer == layers->rend()) {
- ALOGE("Frame has no overlays");
- return -EINVAL;
- }
-
- DrmCompositionLayer_t &comp_layer = *last_layer;
- DrmPlane *stolen_plane = NULL;
- std::swap(stolen_plane, comp_layer.plane);
-
DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
if (connector == NULL) {
ALOGE("Failed to determine display mode: no connector for display %d",
@@ -186,15 +175,6 @@ int DrmDisplayCompositor::ApplyPreComposite(
return -ENOMEM;
}
- if (!pre_compositor_) {
- pre_compositor_.reset(new GLWorkerCompositor());
- ret = pre_compositor_->Init();
- if (ret) {
- ALOGE("Failed to initialize OpenGL compositor %d", ret);
- return ret;
- }
- }
-
std::vector<hwc_layer_1_t> pre_comp_layers;
for (auto &comp_layer : *layers) {
if (comp_layer.plane == NULL) {
@@ -219,48 +199,35 @@ int DrmDisplayCompositor::ApplyPreComposite(
return ret;
}
- display_comp->RemoveNoPlaneLayers();
-
- hwc_layer_1_t pre_comp_output_layer;
- memset(&pre_comp_output_layer, 0, sizeof(pre_comp_output_layer));
- pre_comp_output_layer.compositionType = HWC_OVERLAY;
+ DrmCompositionLayer_t &pre_comp_layer =
+ layers->at(display_comp->pre_composition_layer_index());
+ ret = display_comp->importer()->ImportBuffer(fb.buffer()->handle,
+ &pre_comp_layer.bo);
+ 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.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_comp_output_layer.sourceCropf.top =
- pre_comp_output_layer.displayFrame.top = 0;
- pre_comp_output_layer.sourceCropf.left =
- pre_comp_output_layer.displayFrame.left = 0;
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();
- ret = display_comp->AddLayer(&pre_comp_output_layer,
- drm_->GetCrtcForDisplay(display_), stolen_plane);
- if (ret) {
- ALOGE("Failed to add composited layer %d", ret);
- return ret;
- }
-
fb.set_release_fence_fd(pre_comp_output_layer.releaseFenceFd);
framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
+ display_comp->RemoveNoPlaneLayers();
+ display_comp->SignalPreCompositionDone();
return ret;
}
int DrmDisplayCompositor::ApplyFrame(DrmDisplayComposition *display_comp) {
int ret = 0;
- DrmCompositionLayerVector_t *layers = display_comp->GetCompositionLayers();
- bool use_pre_comp = std::any_of(layers->begin(), layers->end(),
- drm_composition_layer_has_no_plane);
-
- if (use_pre_comp) {
+ if (display_comp->pre_composition_layer_index() >= 0) {
ret = ApplyPreComposite(display_comp);
if (ret)
return ret;
@@ -272,6 +239,7 @@ int DrmDisplayCompositor::ApplyFrame(DrmDisplayComposition *display_comp) {
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;
@@ -409,6 +377,16 @@ int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
int DrmDisplayCompositor::Composite() {
ATRACE_CALL();
+
+ if (!pre_compositor_) {
+ pre_compositor_.reset(new GLWorkerCompositor());
+ int ret = pre_compositor_->Init();
+ if (ret) {
+ ALOGE("Failed to initialize OpenGL compositor %d", ret);
+ return ret;
+ }
+ }
+
int ret = pthread_mutex_lock(&lock_);
if (ret) {
ALOGE("Failed to acquire compositor lock %d", ret);
diff --git a/drmresources.cpp b/drmresources.cpp
index feb5187..32fe5cc 100644
--- a/drmresources.cpp
+++ b/drmresources.cpp
@@ -467,18 +467,17 @@ int DrmResources::SetDpmsMode(int display, uint64_t mode) {
return -EINVAL;
}
- DrmComposition *comp = compositor_.CreateComposition(NULL);
+ std::unique_ptr<DrmComposition> comp(compositor_.CreateComposition(NULL));
if (!comp) {
ALOGE("Failed to create composition for dpms on %d", display);
return -ENOMEM;
}
- int ret = comp->AddDpmsMode(display, mode);
+ int ret = comp->SetDpmsMode(display, mode);
if (ret) {
ALOGE("Failed to add dpms %ld to composition on %d %d", mode, display, ret);
- delete comp;
return ret;
}
- ret = compositor_.QueueComposition(comp);
+ ret = compositor_.QueueComposition(std::move(comp));
if (ret) {
ALOGE("Failed to queue dpms composition on %d %d", display, ret);
return ret;
diff --git a/glworker.cpp b/glworker.cpp
index fe2fd66..10e895f 100644
--- a/glworker.cpp
+++ b/glworker.cpp
@@ -444,7 +444,7 @@ static int CreateTextureFromHandle(EGLDisplay egl_display,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, 0);
- out->image.reset(image);
+ out->image.reset(egl_display, image);
out->texture.reset(texture);
return 0;
@@ -567,13 +567,13 @@ int GLWorkerCompositor::Composite(hwc_layer_1 *layers, size_t num_layers,
GLint frame_height = framebuffer->getHeight();
EGLSyncKHR finished_sync;
- AutoEGLImageKHR egl_fb_image(
+ AutoEGLDisplayImage egl_fb_image(
+ egl_display_,
eglCreateImageKHR(egl_display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
(EGLClientBuffer)framebuffer->getNativeBuffer(),
- NULL /* no attribs */),
- EGLImageDeleter(egl_display_));
+ NULL /* no attribs */));
- if (egl_fb_image.get() == EGL_NO_IMAGE_KHR) {
+ if (egl_fb_image.image() == EGL_NO_IMAGE_KHR) {
ALOGE("Failed to make image from target buffer: %s", GetEGLError());
return -EINVAL;
}
@@ -583,7 +583,7 @@ int GLWorkerCompositor::Composite(hwc_layer_1 *layers, size_t num_layers,
AutoGLTexture gl_fb_tex_auto(gl_fb_tex);
glBindTexture(GL_TEXTURE_2D, gl_fb_tex);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
- (GLeglImageOES)egl_fb_image.get());
+ (GLeglImageOES)egl_fb_image.image());
glBindTexture(GL_TEXTURE_2D, 0);
GLuint gl_fb;
@@ -610,9 +610,10 @@ int GLWorkerCompositor::Composite(hwc_layer_1 *layers, size_t num_layers,
continue;
}
- layer_textures.emplace_back(egl_display_);
+ layer_textures.emplace_back();
ret = CreateTextureFromHandle(egl_display_, layer->handle,
&layer_textures.back());
+
if (!ret) {
ret = EGLFenceWait(egl_display_, layer->acquireFenceFd);
layer->acquireFenceFd = -1;
diff --git a/glworker.h b/glworker.h
index 8252b62..11f4bd9 100644
--- a/glworker.h
+++ b/glworker.h
@@ -17,7 +17,6 @@
#ifndef ANDROID_GL_WORKER_H_
#define ANDROID_GL_WORKER_H_
-#include <memory>
#include <vector>
#define EGL_EGLEXT_PROTOTYPES
@@ -30,53 +29,10 @@
#include <ui/GraphicBuffer.h>
-struct hwc_layer_1;
+#include "autogl.h"
namespace android {
-#define AUTO_GL_TYPE(name, type, zero, deleter) \
- struct name##Deleter { \
- typedef type pointer; \
- \
- void operator()(pointer p) const { \
- if (p != zero) { \
- deleter; \
- } \
- } \
- }; \
- typedef std::unique_ptr<type, name##Deleter> name;
-
-AUTO_GL_TYPE(AutoGLFramebuffer, GLuint, 0, glDeleteFramebuffers(1, &p))
-AUTO_GL_TYPE(AutoGLBuffer, GLuint, 0, glDeleteBuffers(1, &p))
-AUTO_GL_TYPE(AutoGLTexture, GLuint, 0, glDeleteTextures(1, &p))
-AUTO_GL_TYPE(AutoGLShader, GLint, 0, glDeleteShader(p))
-AUTO_GL_TYPE(AutoGLProgram, GLint, 0, glDeleteProgram(p))
-
-struct EGLImageDeleter {
- typedef EGLImageKHR pointer;
-
- EGLDisplay egl_display_;
-
- EGLImageDeleter(EGLDisplay egl_display) : egl_display_(egl_display) {
- }
-
- void operator()(EGLImageKHR p) const {
- if (p != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(egl_display_, p);
- }
- }
-};
-typedef std::unique_ptr<EGLImageKHR, EGLImageDeleter> AutoEGLImageKHR;
-
-struct AutoEGLImageAndGLTexture {
- AutoEGLImageKHR image;
- AutoGLTexture texture;
-
- AutoEGLImageAndGLTexture(EGLDisplay egl_display)
- : image(EGL_NO_IMAGE_KHR, EGLImageDeleter(egl_display)) {
- }
-};
-
class GLWorkerCompositor {
public:
GLWorkerCompositor();
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 787be72..a00c95f 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -22,12 +22,14 @@
#include "importer.h"
#include "vsyncworker.h"
+#include <stdlib.h>
+
+#include <map>
+#include <vector>
+
#include <errno.h>
#include <fcntl.h>
-#include <list>
-#include <map>
#include <pthread.h>
-#include <stdlib.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <xf86drm.h>
@@ -109,8 +111,7 @@ static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
}
static void hwc_set_cleanup(size_t num_displays,
- hwc_display_contents_1_t **display_contents,
- DrmComposition *composition) {
+ hwc_display_contents_1_t **display_contents) {
for (int i = 0; i < (int)num_displays; ++i) {
if (!display_contents[i])
continue;
@@ -128,32 +129,10 @@ static void hwc_set_cleanup(size_t num_displays,
dc->outbufAcquireFenceFd = -1;
}
}
-
- delete composition;
-}
-
-static int hwc_add_layer(int display, hwc_context_t *ctx, hwc_layer_1_t *layer,
- DrmComposition *composition) {
- hwc_drm_bo_t bo;
- int ret = ctx->importer->ImportBuffer(layer->handle, &bo);
- if (ret) {
- ALOGE("Failed to import handle to bo %d", ret);
- return ret;
- }
-
- ret = composition->AddLayer(display, layer, &bo);
- if (!ret)
- return 0;
-
- int destroy_ret = ctx->importer->ReleaseBuffer(&bo);
- if (destroy_ret)
- ALOGE("Failed to destroy buffer %d", destroy_ret);
-
- return ret;
}
-static void hwc_add_layer_to_retire_fence(hwc_layer_1_t *layer,
- hwc_display_contents_1_t *display_contents) {
+static void hwc_add_layer_to_retire_fence(
+ hwc_layer_1_t *layer, hwc_display_contents_1_t *display_contents) {
if (layer->releaseFenceFd < 0)
return;
@@ -171,64 +150,77 @@ static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
hwc_display_contents_1_t **display_contents) {
ATRACE_CALL();
struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
- DrmComposition *composition =
- ctx->drm.compositor()->CreateComposition(ctx->importer);
+ 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, NULL);
+ hwc_set_cleanup(num_displays, display_contents);
return -EINVAL;
}
- int ret;
+ std::vector<DrmCompositionDisplayLayersMap> layers_map;
+ std::vector<std::vector<size_t>> layers_indices;
+ layers_map.reserve(num_displays);
+ layers_indices.reserve(num_displays);
+
for (int i = 0; i < (int)num_displays; ++i) {
if (!display_contents[i])
continue;
-
hwc_display_contents_1_t *dc = display_contents[i];
- int j;
- unsigned num_layers = 0;
+
+ layers_map.emplace_back();
+ DrmCompositionDisplayLayersMap &map = layers_map[i];
+ map.display = i;
+ map.layers = dc->hwLayers;
+
+ std::vector<size_t> indices_to_composite;
unsigned num_dc_layers = dc->numHwLayers;
- for (j = 0; j < (int)num_dc_layers; ++j) {
+ 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)
- num_layers++;
+ indices_to_composite.push_back(j);
}
- unsigned num_planes = composition->GetRemainingLayers(i, num_layers);
+ map.num_layers = indices_to_composite.size();
+ layers_indices.emplace_back(std::move(indices_to_composite));
+ map.layer_indices = layers_indices.back().data();
+ }
- if (num_layers > num_planes) {
- ALOGE("Can not composite %u with only %u planes", num_layers, num_planes);
- }
+ 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 (j = 0; num_planes && j < (int)num_dc_layers; ++j) {
+ 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)
- continue;
-
- ret = hwc_add_layer(i, ctx, layer, composition);
- if (ret) {
- ALOGE("Add layer failed %d", ret);
- hwc_set_cleanup(num_displays, display_contents, composition);
- return ret;
- }
- hwc_add_layer_to_retire_fence(layer, dc);
-
- --num_planes;
+ if (layer->compositionType == HWC_OVERLAY)
+ hwc_add_layer_to_retire_fence(layer, dc);
}
}
- ret = ctx->drm.compositor()->QueueComposition(composition);
- composition = NULL;
if (ret) {
ALOGE("Failed to queue the composition");
- hwc_set_cleanup(num_displays, display_contents, NULL);
- return ret;
}
- hwc_set_cleanup(num_displays, display_contents, NULL);
+ hwc_set_cleanup(num_displays, display_contents);
return ret;
}