diff options
-rw-r--r-- | autogl.h | 110 | ||||
-rw-r--r-- | drmcomposition.cpp | 58 | ||||
-rw-r--r-- | drmcomposition.h | 18 | ||||
-rw-r--r-- | drmcompositor.cpp | 4 | ||||
-rw-r--r-- | drmcompositor.h | 3 | ||||
-rw-r--r-- | drmdisplaycomposition.cpp | 243 | ||||
-rw-r--r-- | drmdisplaycomposition.h | 24 | ||||
-rw-r--r-- | drmdisplaycompositor.cpp | 68 | ||||
-rw-r--r-- | drmresources.cpp | 7 | ||||
-rw-r--r-- | glworker.cpp | 15 | ||||
-rw-r--r-- | glworker.h | 46 | ||||
-rw-r--r-- | hwcomposer.cpp | 112 |
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; @@ -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; } |