[framebuffer] Use display layer API
Test: Run gfxtest and vkcube
Change-Id: I5f97af64f8f3c5efaf7acf8c23388f230b782a1b
diff --git a/system/ulib/framebuffer/framebuffer.c b/system/ulib/framebuffer/framebuffer.c
index de1bcde..21a76f0 100644
--- a/system/ulib/framebuffer/framebuffer.c
+++ b/system/ulib/framebuffer/framebuffer.c
@@ -25,17 +25,33 @@
static int32_t txid;
static int32_t display_id;
+static int32_t layer_id;
static int32_t width;
static int32_t height;
static int32_t stride;
static zx_pixel_format_t format;
+static bool type_set;
+static uint32_t image_type;
static zx_handle_t vmo = ZX_HANDLE_INVALID;
static bool inited = false;
static bool in_single_buffer_mode;
+static zx_status_t set_layer_config(int32_t layer_id, uint32_t width, uint32_t height,
+ zx_pixel_format_t format, int32_t type) {
+ fuchsia_display_ControllerSetLayerPrimaryConfigRequest layer_cfg_msg;
+ layer_cfg_msg.hdr.ordinal = fuchsia_display_ControllerSetLayerPrimaryConfigOrdinal;
+ layer_cfg_msg.layer_id = layer_id;
+ layer_cfg_msg.image_config.width = width;
+ layer_cfg_msg.image_config.height = height;
+ layer_cfg_msg.image_config.pixel_format = format;
+ layer_cfg_msg.image_config.type = type;
+
+ return zx_channel_write(dc_handle, 0, &layer_cfg_msg, sizeof(layer_cfg_msg), NULL, 0);
+}
+
zx_status_t fb_bind(bool single_buffer, const char** err_msg_out) {
const char* err_msg;
if (!err_msg_out) {
@@ -116,13 +132,62 @@
goto err;
}
+ fuchsia_display_ControllerCreateLayerRequest create_layer_msg;
+ create_layer_msg.hdr.ordinal = fuchsia_display_ControllerCreateLayerOrdinal;
+
+ fuchsia_display_ControllerCreateLayerResponse create_layer_rsp;
+ zx_channel_call_args_t call_args = {};
+ call_args.wr_bytes = &create_layer_msg;
+ call_args.rd_bytes = &create_layer_rsp;
+ call_args.wr_num_bytes = sizeof(create_layer_msg);
+ call_args.rd_num_bytes = sizeof(create_layer_rsp);
+ if ((status = zx_channel_call(dc_handle, 0, ZX_TIME_INFINITE, &call_args,
+ &actual_bytes, &actual_handles, &read_status)) != ZX_OK) {
+ *err_msg_out = "Create layer call failed";
+ status = (status == ZX_ERR_CALL_FAILED ? read_status : status);
+ goto err;
+ }
+ if (create_layer_rsp.res != ZX_OK) {
+ *err_msg_out = "Failed to create layer";
+ status = create_layer_rsp.res;
+ goto err;
+ }
+
+ uint8_t fidl_bytes[sizeof(fuchsia_display_ControllerSetDisplayLayersRequest)
+ + FIDL_ALIGN(sizeof(uint64_t))];
+ fuchsia_display_ControllerSetDisplayLayersRequest* set_display_layer_request =
+ (fuchsia_display_ControllerSetDisplayLayersRequest*) fidl_bytes;
+ *(uint64_t*)(fidl_bytes + sizeof(fuchsia_display_ControllerSetDisplayLayersRequest)) =
+ create_layer_rsp.layer_id;
+
+ set_display_layer_request->hdr.ordinal = fuchsia_display_ControllerSetDisplayLayersOrdinal;
+ set_display_layer_request->display_id = display->id;
+ set_display_layer_request->layer_ids.count = 1;
+ set_display_layer_request->layer_ids.data = (void*) FIDL_ALLOC_PRESENT;
+
+ if ((status = zx_channel_write(dc_handle, 0, fidl_bytes,
+ sizeof(fidl_bytes), NULL, 0)) != ZX_OK) {
+ *err_msg_out = "Failed to set display layers";
+ goto err;
+ }
+
+ if ((status = set_layer_config(create_layer_rsp.layer_id, mode->horizontal_resolution,
+ mode->vertical_resolution, pixel_format,
+ IMAGE_TYPE_SIMPLE)) != ZX_OK) {
+ *err_msg_out = "Failed to set layer config";
+ goto err;
+ }
+
display_id = display->id;
+ layer_id = create_layer_rsp.layer_id;
width = mode->horizontal_resolution;
height = mode->vertical_resolution;
format = pixel_format;
stride = stride_rsp.stride;
+ type_set = false;
+
inited = true;
if (single_buffer) {
@@ -236,6 +301,16 @@
ZX_ASSERT(inited && !in_single_buffer_mode);
zx_status_t status;
+ if (type_set && type != image_type) {
+ return ZX_ERR_BAD_STATE;
+ } else if (!type_set && type != IMAGE_TYPE_SIMPLE) {
+ if ((status = set_layer_config(layer_id, width, height, format, type)) != ZX_OK) {
+ return status;
+ }
+ image_type = type;
+ type_set = true;
+ }
+
fuchsia_display_ControllerImportVmoImageRequest import_msg;
import_msg.hdr.ordinal = fuchsia_display_ControllerImportVmoImageOrdinal;
import_msg.hdr.txid = txid++;
@@ -322,10 +397,10 @@
ZX_ASSERT(inited && !in_single_buffer_mode);
zx_status_t status;
- fuchsia_display_ControllerSetDisplayImageRequest set_msg;
- set_msg.hdr.ordinal = fuchsia_display_ControllerSetDisplayImageOrdinal;
+ fuchsia_display_ControllerSetLayerImageRequest set_msg;
+ set_msg.hdr.ordinal = fuchsia_display_ControllerSetLayerImageOrdinal;
set_msg.hdr.txid = txid++;
- set_msg.display = display_id;
+ set_msg.layer_id = layer_id;
set_msg.image_id = image_id;
set_msg.wait_event_id = wait_event_id;
set_msg.present_event_id = present_event_id;
diff --git a/system/ulib/framebuffer/include/lib/framebuffer/framebuffer.h b/system/ulib/framebuffer/include/lib/framebuffer/framebuffer.h
index d10d201..6de608d 100644
--- a/system/ulib/framebuffer/include/lib/framebuffer/framebuffer.h
+++ b/system/ulib/framebuffer/include/lib/framebuffer/framebuffer.h
@@ -40,7 +40,7 @@
//
// If |type| is 0, the imported image has a linear memory layout. For any other
// values, it is the responsibility of the image producer and display driver to
-// coordinate the meaning of |type|.
+// coordinate the meaning of |type|. All imported images must have the same type.
zx_status_t fb_import_image(zx_handle_t handle, uint32_t type, uint64_t *id_out);
void fb_release_image(uint64_t id);