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
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 @@
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 @@
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 @@
}
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 @@
--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 @@
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 @@
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");