diff options
author | Puneet Kumar <puneetster@google.com> | 2015-07-30 03:36:46 +0000 |
---|---|---|
committer | Puneet Kumar <puneetster@google.com> | 2015-07-30 03:36:46 +0000 |
commit | d078e4cab78f81057cd25355199caba5a147342e (patch) | |
tree | 6bd39b93a08a71ce7cf5f392c4254e68671ad78e | |
parent | abebc7a78fe8a4df6495c8e5064719dc92b04004 (diff) | |
download | drm_hwcomposer-d078e4cab78f81057cd25355199caba5a147342e.tar.gz |
Revert "drm_hwcomposer: remove GLCompositor and the GLWorker thread"
This reverts commit abebc7a78fe8a4df6495c8e5064719dc92b04004.
For now until we figure out a more stable solution for SF/hwc
Change-Id: I7a505fc67873f943704e8b48db4167b9beca7691
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | gl_compositor.cpp | 295 | ||||
-rw-r--r-- | gl_compositor.h | 61 | ||||
-rw-r--r-- | glworker.cpp | 192 | ||||
-rw-r--r-- | glworker.h | 40 | ||||
-rw-r--r-- | hwcomposer.cpp | 213 |
6 files changed, 801 insertions, 1 deletions
@@ -50,6 +50,7 @@ LOCAL_SRC_FILES := \ drmmode.cpp \ drmplane.cpp \ drmproperty.cpp \ + gl_compositor.cpp \ glworker.cpp \ hwcomposer.cpp \ seperate_rects.cpp \ diff --git a/gl_compositor.cpp b/gl_compositor.cpp new file mode 100644 index 0000000..0605c04 --- /dev/null +++ b/gl_compositor.cpp @@ -0,0 +1,295 @@ +/* + * 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. + */ + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS +#define LOG_TAG "GLCompositor" + +#include <vector> + +#include <cutils/log.h> + +#include <ui/GraphicBuffer.h> +#include <utils/Trace.h> + +#include <sync/sync.h> +#include <sw_sync.h> + +#include "drm_hwcomposer.h" + +#include "gl_compositor.h" +#include "glworker.h" + +namespace android { + +static const char *get_gl_error(void); +static const char *get_egl_error(void); +static bool has_extension(const char *extension, const char *extensions); + +template <typename T> +int AllocResource(std::vector<T> &array) { + for (typename std::vector<T>::iterator it = array.begin(); it != array.end(); + ++it) { + if (!it->is_some()) { + return std::distance(array.begin(), it); + } + } + + array.push_back(T()); + return array.size() - 1; +} + +template <typename T> +void FreeResource(std::vector<T> &array, int index) { + if (index == (int)array.size() - 1) { + array.pop_back(); + } else if (index >= 0 && (unsigned)index < array.size()) { + array[index].Reset(); + } +} + +struct GLTarget { + sp<GraphicBuffer> fb; + bool forgotten; + unsigned composition_count; + + GLTarget() : forgotten(true), composition_count(0) { + } + + void Reset() { + fb.clear(); + forgotten = true; + composition_count = 0; + } + + bool is_some() const { + return fb != NULL; + } +}; + +struct GLCompositor::priv_data { + int current_target; + std::vector<GLTarget> targets; + std::vector<GLComposition *> compositions; + + GLWorker worker; + + priv_data() : current_target(-1) { + } +}; + +class GLComposition : public Composition { + public: + struct LayerData { + hwc_layer_1 layer; + hwc_drm_bo bo; + }; + + GLComposition(GLCompositor *owner, Importer *imp) + : compositor(owner), importer(imp), target_handle(-1), timeline_fd(-1) { + int ret = sw_sync_timeline_create(); + if (ret < 0) { + ALOGE("Failed to create sw sync timeline %d", ret); + } + timeline_fd = ret; + } + + virtual ~GLComposition() { + if (timeline_fd >= 0) + close(timeline_fd); + + if (compositor == NULL) { + return; + } + + // Removes this composition from the owning compositor automatically. + std::vector<GLComposition *> &compositions = + compositor->priv_->compositions; + std::vector<GLComposition *>::iterator it = + std::find(compositions.begin(), compositions.end(), this); + if (it != compositions.end()) { + compositions.erase(it); + } + + GLTarget *target = &compositor->priv_->targets[target_handle]; + target->composition_count--; + compositor->CheckAndDestroyTarget(target_handle); + } + + virtual int AddLayer(int display, hwc_layer_1 *layer, hwc_drm_bo *bo) { + (void)display; + if (layer->compositionType != HWC_OVERLAY) { + ALOGE("Must add layers with compositionType == HWC_OVERLAY"); + return 1; + } + + if (layer->handle == 0) { + ALOGE("Must add layers with valid buffer handle"); + return 1; + } + + layer->releaseFenceFd = sw_sync_fence_create( + timeline_fd, "GLComposition release fence", layers.size() + 1); + + layers.push_back(*layer); + + return importer->ReleaseBuffer(bo); + } + + virtual unsigned GetRemainingLayers(int display, unsigned num_needed) const { + (void)display; + return num_needed; + } + + GLCompositor *compositor; + Importer *importer; + int target_handle; + int timeline_fd; + std::vector<hwc_layer_1> layers; +}; + +GLCompositor::GLCompositor() { + priv_ = new priv_data; +} + +GLCompositor::~GLCompositor() { + for (std::vector<GLComposition *>::iterator it = priv_->compositions.end(); + it != priv_->compositions.begin(); it = priv_->compositions.end()) { + --it; + + // Prevents compositor from trying to erase itself + (*it)->compositor = NULL; + delete *it; + priv_->compositions.erase(it); + } + + delete priv_; +} + +int GLCompositor::Init() { + return priv_->worker.Init(); +} + +Targeting *GLCompositor::targeting() { + return (Targeting *)this; +} + +int GLCompositor::CreateTarget(sp<GraphicBuffer> &buffer) { + int ret; + + int target_handle = AllocResource(priv_->targets); + GLTarget *target = &priv_->targets[target_handle]; + + target->fb = buffer; + target->forgotten = false; + + return target_handle; +} + +void GLCompositor::SetTarget(int target_handle) { + if (target_handle >= 0 && (unsigned)target_handle < priv_->targets.size()) { + GLTarget *target = &priv_->targets[target_handle]; + if (target->is_some()) { + priv_->current_target = target_handle; + return; + } + } + + priv_->current_target = -1; +} + +void GLCompositor::ForgetTarget(int target_handle) { + if (target_handle >= 0 && (unsigned)target_handle < priv_->targets.size()) { + if (target_handle == priv_->current_target) { + priv_->current_target = -1; + } + + GLTarget *target = &priv_->targets[target_handle]; + if (target->is_some()) { + target->forgotten = true; + CheckAndDestroyTarget(target_handle); + return; + } + } + + ALOGE("Failed to forget target because of invalid handle"); +} + +void GLCompositor::CheckAndDestroyTarget(int target_handle) { + GLTarget *target = &priv_->targets[target_handle]; + if (target->composition_count == 0 && target->forgotten) { + FreeResource(priv_->targets, target_handle); + } +} + +Composition *GLCompositor::CreateComposition(Importer *importer) { + if (priv_->current_target >= 0 && + (unsigned)priv_->current_target < priv_->targets.size()) { + GLTarget *target = &priv_->targets[priv_->current_target]; + if (target->is_some()) { + GLComposition *composition = new GLComposition(this, importer); + composition->target_handle = priv_->current_target; + target->composition_count++; + priv_->compositions.push_back(composition); + return composition; + } + } + + ALOGE("Failed to create composition because of invalid target handle %d", + priv_->current_target); + + return NULL; +} + +int GLCompositor::QueueComposition(Composition *composition) { + if (composition) { + GLComposition *gl_composition = (GLComposition *)composition; + int ret = DoComposition(gl_composition); + gl_composition->timeline_fd = -1; + delete composition; + return ret; + } + + ALOGE("Failed to queue composition because of invalid composition handle"); + + return -EINVAL; +} + +int GLCompositor::Composite() { + return 0; +} + +int GLCompositor::DoComposition(GLComposition *composition) { + ATRACE_CALL(); + int ret = 0; + + GLTarget *target = &priv_->targets[composition->target_handle]; + GLWorker::Work work; + work.layers = composition->layers.data(); + work.num_layers = composition->layers.size(); + work.timeline_fd = composition->timeline_fd; + work.framebuffer = target->fb; + + ret = priv_->worker.DoWork(&work); + + if (work.timeline_fd >= 0) { + sw_sync_timeline_inc(work.timeline_fd, work.num_layers + 1); + close(work.timeline_fd); + } + + return ret; +} + +} // namespace android diff --git a/gl_compositor.h b/gl_compositor.h new file mode 100644 index 0000000..450ca67 --- /dev/null +++ b/gl_compositor.h @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#include <stdint.h> +#include <stdint.h> +#include "compositor.h" + +struct hwc_layer_1; +struct hwc_import_context; + +namespace android { + +class GLComposition; + +class GLCompositor : public Compositor, public Targeting { + public: + GLCompositor(); + virtual ~GLCompositor(); + + virtual int Init(); + virtual Targeting *targeting(); + virtual int CreateTarget(sp<android::GraphicBuffer> &buffer); + virtual void SetTarget(int target); + virtual void ForgetTarget(int target); + virtual Composition *CreateComposition(Importer *importer); + virtual int QueueComposition(Composition *composition); + virtual int Composite(); + + private: + struct priv_data; + struct texture_from_handle; + + struct priv_data *priv_; + + int BeginContext(); + int EndContext(); + int GenerateShaders(); + int DoComposition(GLComposition *composition); + int DoFenceWait(int acquireFenceFd); + int CreateTextureFromHandle(buffer_handle_t handle, + struct texture_from_handle *tex); + void DestroyTextureFromHandle(const struct texture_from_handle &tex); + void CheckAndDestroyTarget(int target_handle); + + friend GLComposition; +}; + +} // namespace android diff --git a/glworker.cpp b/glworker.cpp index df6a8f2..e0d337b 100644 --- a/glworker.cpp +++ b/glworker.cpp @@ -23,6 +23,9 @@ #include <sys/resource.h> +#include <sync/sync.h> +#include <sw_sync.h> + #include <hardware/hardware.h> #include <hardware/hwcomposer.h> @@ -707,4 +710,193 @@ int GLWorkerCompositor::CompositeAndFinish(hwc_layer_1 *layers, return ret; } +int GLWorker::DoComposition(GLWorkerCompositor &compositor, Work *work) { + int ret = + compositor.Composite(work->layers, work->num_layers, work->framebuffer); + + int timeline_fd = work->timeline_fd; + work->timeline_fd = -1; + + if (ret) { + worker_ret_ = ret; + glFinish(); + sw_sync_timeline_inc(timeline_fd, work->num_layers); + close(timeline_fd); + return pthread_cond_signal(&work_done_cond_); + } + + unsigned timeline_count = work->num_layers + 1; + worker_ret_ = sw_sync_fence_create(timeline_fd, "GLComposition done fence", + timeline_count); + ret = pthread_cond_signal(&work_done_cond_); + + glFinish(); + + sw_sync_timeline_inc(timeline_fd, timeline_count); + close(timeline_fd); + + return ret; +} + +GLWorker::GLWorker() : initialized_(false) { +} + +GLWorker::~GLWorker() { + if (!initialized_) + return; + + if (SignalWorker(NULL, true) != 0 || pthread_join(thread_, NULL) != 0) + pthread_kill(thread_, SIGTERM); + + pthread_cond_destroy(&work_ready_cond_); + pthread_cond_destroy(&work_done_cond_); + pthread_mutex_destroy(&lock_); +} + +#define TRY(x, n, g) \ + ret = x; \ + if (ret) { \ + ALOGE("Failed to " n " %d", ret); \ + g; \ + } + +#define TRY_RETURN(x, n) TRY(x, n, return ret) + +int GLWorker::Init() { + int ret = 0; + + worker_work_ = NULL; + worker_exit_ = false; + worker_ret_ = -1; + + ret = pthread_cond_init(&work_ready_cond_, NULL); + if (ret) { + ALOGE("Failed to int GLThread condition %d", ret); + return ret; + } + + ret = pthread_cond_init(&work_done_cond_, NULL); + if (ret) { + ALOGE("Failed to int GLThread condition %d", ret); + pthread_cond_destroy(&work_ready_cond_); + return ret; + } + + ret = pthread_mutex_init(&lock_, NULL); + if (ret) { + ALOGE("Failed to init GLThread lock %d", ret); + pthread_cond_destroy(&work_ready_cond_); + pthread_cond_destroy(&work_done_cond_); + return ret; + } + + ret = pthread_create(&thread_, NULL, StartRoutine, this); + if (ret) { + ALOGE("Failed to create GLThread %d", ret); + pthread_cond_destroy(&work_ready_cond_); + pthread_cond_destroy(&work_done_cond_); + pthread_mutex_destroy(&lock_); + return ret; + } + + initialized_ = true; + + TRY_RETURN(pthread_mutex_lock(&lock_), "lock GLThread"); + + while (!worker_exit_ && worker_ret_ != 0) + TRY(pthread_cond_wait(&work_done_cond_, &lock_), "wait on condition", + goto out_unlock); + + ret = worker_ret_; + +out_unlock: + int unlock_ret = pthread_mutex_unlock(&lock_); + if (unlock_ret) { + ret = unlock_ret; + ALOGE("Failed to unlock GLThread %d", unlock_ret); + } + return ret; +} + +int GLWorker::SignalWorker(Work *work, bool worker_exit) { + int ret = 0; + if (worker_exit_) + return -EINVAL; + TRY_RETURN(pthread_mutex_lock(&lock_), "lock GLThread"); + worker_work_ = work; + worker_exit_ = worker_exit; + ret = pthread_cond_signal(&work_ready_cond_); + if (ret) { + ALOGE("Failed to signal GLThread caller %d", ret); + pthread_mutex_unlock(&lock_); + return ret; + } + ret = pthread_cond_wait(&work_done_cond_, &lock_); + if (ret) { + ALOGE("Failed to wait on GLThread %d", ret); + pthread_mutex_unlock(&lock_); + return ret; + } + + ret = worker_ret_; + if (ret) { + pthread_mutex_unlock(&lock_); + return ret; + } + TRY_RETURN(pthread_mutex_unlock(&lock_), "unlock GLThread"); + return ret; +} + +int GLWorker::DoWork(Work *work) { + return SignalWorker(work, false); +} + +void GLWorker::WorkerRoutine() { + int ret = 0; + + TRY(pthread_mutex_lock(&lock_), "lock GLThread", return ); + + GLWorkerCompositor compositor; + + TRY(compositor.Init(), "initialize GL", goto out_signal_done); + + worker_ret_ = 0; + TRY(pthread_cond_signal(&work_done_cond_), "signal GLThread caller", + goto out_signal_done); + + while (true) { + while (worker_work_ == NULL && !worker_exit_) + TRY(pthread_cond_wait(&work_ready_cond_, &lock_), "wait on condition", + goto out_signal_done); + + if (worker_exit_) { + ret = 0; + break; + } + + ret = DoComposition(compositor, worker_work_); + + worker_work_ = NULL; + if (ret) { + break; + } + } + +out_signal_done: + worker_exit_ = true; + worker_ret_ = ret; + TRY(pthread_cond_signal(&work_done_cond_), "signal GLThread caller", + goto out_unlock); +out_unlock: + TRY(pthread_mutex_unlock(&lock_), "unlock GLThread", return ); +} + +/* static */ +void *GLWorker::StartRoutine(void *arg) { + setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); + GLWorker *worker = (GLWorker *)arg; + worker->WorkerRoutine(); + return NULL; +} + } // namespace android @@ -17,6 +17,8 @@ #ifndef ANDROID_GL_WORKER_H_ #define ANDROID_GL_WORKER_H_ +#include <pthread.h> + #include <memory> #include <vector> @@ -96,6 +98,44 @@ class GLWorkerCompositor { std::vector<AutoGLProgram> blend_programs_; AutoGLBuffer vertex_buffer_; }; + +class GLWorker { + public: + struct Work { + hwc_layer_1 *layers; + size_t num_layers; + int timeline_fd; + sp<GraphicBuffer> framebuffer; + + Work() = default; + Work(const Work &rhs) = delete; + }; + + GLWorker(); + ~GLWorker(); + + int Init(); + + int DoWork(Work *work); + + private: + bool initialized_; + pthread_t thread_; + pthread_mutex_t lock_; + pthread_cond_t work_ready_cond_; + pthread_cond_t work_done_cond_; + Work *worker_work_; + bool work_ready_; + bool worker_exit_; + int worker_ret_; + + void WorkerRoutine(); + int DoComposition(GLWorkerCompositor &compositor, Work *work); + + int SignalWorker(Work *work, bool worker_exit); + + static void *StartRoutine(void *arg); +}; } #endif diff --git a/hwcomposer.cpp b/hwcomposer.cpp index b4b1a50..18f6921 100644 --- a/hwcomposer.cpp +++ b/hwcomposer.cpp @@ -19,6 +19,7 @@ #include "drm_hwcomposer.h" #include "drmresources.h" +#include "gl_compositor.h" #include "importer.h" #include "vsyncworker.h" @@ -37,6 +38,10 @@ #include <cutils/properties.h> #include <hardware/hardware.h> #include <hardware/hwcomposer.h> +#include <sw_sync.h> +#include <sync/sync.h> +#include <ui/GraphicBuffer.h> +#include <ui/PixelFormat.h> #include <utils/Trace.h> #define UM_PER_INCH 25400 @@ -44,6 +49,80 @@ namespace android { +struct hwc_drm_display_framebuffer { + hwc_drm_display_framebuffer() : release_fence_fd_(-1) { + } + + ~hwc_drm_display_framebuffer() { + if (release_fence_fd() >= 0) + close(release_fence_fd()); + } + + bool is_valid() { + return buffer_ != NULL; + } + + sp<GraphicBuffer> buffer() { + return buffer_; + } + + int release_fence_fd() { + return release_fence_fd_; + } + + void set_release_fence_fd(int fd) { + if (release_fence_fd_ >= 0) + close(release_fence_fd_); + release_fence_fd_ = fd; + } + + bool Allocate(uint32_t w, uint32_t h) { + if (is_valid()) { + if (buffer_->getWidth() == w && buffer_->getHeight() == h) + return true; + + if (release_fence_fd_ >= 0) { + if (sync_wait(release_fence_fd_, -1) != 0) { + return false; + } + } + Clear(); + } + buffer_ = new GraphicBuffer(w, h, android::PIXEL_FORMAT_RGBA_8888, + GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_COMPOSER); + release_fence_fd_ = -1; + return is_valid(); + } + + void Clear() { + if (!is_valid()) + return; + + if (release_fence_fd_ >= 0) { + close(release_fence_fd_); + release_fence_fd_ = -1; + } + + buffer_.clear(); + } + + int WaitReleased(int timeout_milliseconds) { + if (!is_valid()) + return 0; + if (release_fence_fd_ < 0) + return 0; + + int ret = sync_wait(release_fence_fd_, timeout_milliseconds); + return ret; + } + + private: + sp<GraphicBuffer> buffer_; + int release_fence_fd_; +}; + + typedef struct hwc_drm_display { struct hwc_context_t *ctx; int display; @@ -51,6 +130,9 @@ typedef struct hwc_drm_display { std::vector<uint32_t> config_ids; VSyncWorker vsync_worker; + + hwc_drm_display_framebuffer fb_chain[HWC_FB_BUFFERS]; + int fb_idx; } hwc_drm_display_t; struct hwc_context_t { @@ -71,6 +153,7 @@ struct hwc_context_t { DisplayMap displays; DrmResources drm; Importer *importer; + GLCompositor pre_compositor; }; static void hwc_dump(struct hwc_composer_device_1* dev, char *buff, @@ -197,9 +280,12 @@ static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays, } unsigned num_planes = composition->GetRemainingLayers(i, num_layers); + bool use_pre_compositor = false; if (num_layers > num_planes) { - ALOGE("Can not composite %u with only %u planes", num_layers, num_planes); + use_pre_compositor = true; + // Reserve one of the planes for the result of the pre compositor. + num_planes--; } for (j = 0; num_planes && j < (int)num_dc_layers; ++j) { @@ -219,6 +305,123 @@ static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays, --num_planes; } + + int last_comp_layer = j; + + if (use_pre_compositor) { + hwc_drm_display_t *hd = &ctx->displays[i]; + struct hwc_drm_display_framebuffer *fb = &hd->fb_chain[hd->fb_idx]; + ret = fb->WaitReleased(-1); + if (ret) { + ALOGE("Failed to wait for framebuffer %d", ret); + hwc_set_cleanup(num_displays, display_contents, composition); + return ret; + } + + DrmConnector *connector = ctx->drm.GetConnectorForDisplay(i); + if (!connector) { + ALOGE("No connector for display %d", i); + hwc_set_cleanup(num_displays, display_contents, composition); + return -ENODEV; + } + + const DrmMode &mode = connector->active_mode(); + if (!fb->Allocate(mode.h_display(), mode.v_display())) { + ALOGE("Failed to allocate framebuffer with size %dx%d", + mode.h_display(), mode.v_display()); + hwc_set_cleanup(num_displays, display_contents, composition); + return -EINVAL; + } + + sp<GraphicBuffer> fb_buffer = fb->buffer(); + if (fb_buffer == NULL) { + ALOGE("Framebuffer is NULL"); + hwc_set_cleanup(num_displays, display_contents, composition); + return -EINVAL; + } + + Targeting *targeting = ctx->pre_compositor.targeting(); + if (targeting == NULL) { + ALOGE("Pre-compositor does not support targeting"); + hwc_set_cleanup(num_displays, display_contents, composition); + return -EINVAL; + } + + int target = targeting->CreateTarget(fb_buffer); + targeting->SetTarget(target); + + Composition *pre_composition = ctx->pre_compositor.CreateComposition(ctx->importer); + if (pre_composition == NULL) { + ALOGE("Failed to create pre-composition"); + targeting->ForgetTarget(target); + hwc_set_cleanup(num_displays, display_contents, composition); + return -EINVAL; + } + + for (j = last_comp_layer; 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, pre_composition); + if (ret) { + ALOGE("Add layer failed %d", ret); + delete pre_composition; + targeting->ForgetTarget(target); + hwc_set_cleanup(num_displays, display_contents, composition); + return ret; + } + } + + ret = ctx->pre_compositor.QueueComposition(pre_composition); + pre_composition = NULL; + + targeting->ForgetTarget(target); + if (ret < 0 && ret != -EALREADY) { + ALOGE("Pre-composition failed %d", ret); + hwc_set_cleanup(num_displays, display_contents, composition); + return ret; + } + + for (j = last_comp_layer; 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; + layer->acquireFenceFd = -1; + } + + hwc_layer_1_t composite_layer; + hwc_rect_t visible_rect; + memset(&composite_layer, 0, sizeof(composite_layer)); + memset(&visible_rect, 0, sizeof(visible_rect)); + + composite_layer.compositionType = HWC_OVERLAY; + composite_layer.handle = fb_buffer->getNativeBuffer()->handle; + composite_layer.sourceCropf.right = composite_layer.displayFrame.right = + visible_rect.right = fb_buffer->getWidth(); + composite_layer.sourceCropf.bottom = composite_layer.displayFrame.bottom = + visible_rect.bottom = fb_buffer->getHeight(); + composite_layer.visibleRegionScreen.numRects = 1; + composite_layer.visibleRegionScreen.rects = &visible_rect; + composite_layer.acquireFenceFd = ret == -EALREADY ? -1 : ret; + // A known invalid fd in case AddLayer does not modify this field. + composite_layer.releaseFenceFd = -1; + composite_layer.planeAlpha = 0xff; + + ret = hwc_add_layer(i, ctx, &composite_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(&composite_layer, dc); + + fb->set_release_fence_fd(composite_layer.releaseFenceFd); + hd->fb_idx = (hd->fb_idx + 1) % HWC_FB_BUFFERS; + } } ret = ctx->drm.compositor()->QueueComposition(composition); @@ -459,6 +662,7 @@ static int hwc_initialize_display(struct hwc_context_t *ctx, int display) { hwc_drm_display_t *hd = &ctx->displays[display]; hd->ctx = ctx; hd->display = display; + hd->fb_idx = 0; int ret = hwc_set_initial_config(hd); if (ret) { @@ -509,6 +713,13 @@ static int hwc_device_open(const struct hw_module_t *module, const char *name, return ret; } + ret = ctx->pre_compositor.Init(); + if (ret) { + ALOGE("Can't initialize OpenGL Compositor object %d", ret); + delete ctx; + return ret; + } + ctx->importer = Importer::CreateInstance(&ctx->drm); if (!ctx->importer) { ALOGE("Failed to create importer instance"); |