From 2987491ac850dc2aa5878bd202e33c24484ad3cb Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Wed, 7 Dec 2011 12:47:14 -0800 Subject: [PATCH 1/4] liboverlay: Add support for interlaced content in updateOverlaySource. UpdateOverlay source didn't have any support for interlaced content. Add the required support. Create a new function to check if the content is interlaced. Change-Id: Ie47b7669461f773b55c71cad6978fc1c8cf4e91b --- liboverlay/overlayLib.cpp | 25 ++++++++++++++++++++----- liboverlay/overlayLib.h | 1 + 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 5245fc2..6f2c604 100755 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -256,8 +256,21 @@ bool overlay::enableBarrier (unsigned int orientation) { int overlay::getColorFormat(int format) { - return (format == HAL_PIXEL_FORMAT_YV12) ? - format : COLOR_FORMAT(format); + if (format == HAL_PIXEL_FORMAT_YV12) + return format; + else if (format & INTERLACE_MASK) + return format ^ HAL_PIXEL_FORMAT_INTERLACE; + else + return COLOR_FORMAT(format); +} + +bool overlay::isInterlacedContent(int format) +{ + if ((format != HAL_PIXEL_FORMAT_YV12) && + (format & INTERLACE_MASK)) + return true; + + return false; } unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll, @@ -970,8 +983,8 @@ bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& inf mOVInfo.z_order = zorder; mOVInfo.alpha = 0xff; mOVInfo.transp_mask = 0xffffffff; - mOVInfo.flags = flags; } + mOVInfo.flags = flags; if (!ignoreFB) mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; else @@ -1051,7 +1064,9 @@ bool OverlayControlChannel::updateOverlaySource(const overlay_buffer_info& info, ovBufInfo.height = info.height; ovBufInfo.format = hw_format; - if (!setOverlayInformation(ovBufInfo, 0, orientation, 0, waitForVsync, UPDATE_REQUEST)) + int flags = isInterlacedContent(info.format) ? MDP_DEINTERLACE : 0; + if (!setOverlayInformation(ovBufInfo, flags, orientation, 0, waitForVsync, + UPDATE_REQUEST)) return false; return startOVRotatorSessions(ovBufInfo, orientation, UPDATE_REQUEST); @@ -1072,7 +1087,7 @@ bool OverlayControlChannel::startControlChannel(int w, int h, int colorFormat = format; // The interlace mask is part of the HAL_PIXEL_FORMAT_YV12 value. Add // an explicit check for the format - if ((format != HAL_PIXEL_FORMAT_YV12) && (format & INTERLACE_MASK)) { + if (isInterlacedContent(format)) { flags |= MDP_DEINTERLACE; // Get the actual format diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 0a502ea..1448f83 100755 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -144,6 +144,7 @@ bool enableBarrier(unsigned int orientation); unsigned int getOverlayConfig (unsigned int format3D, bool poll = true, bool isHDMI = false); int getColorFormat(int format); +bool isInterlacedContent(int format); int get_mdp_format(int format); int get_size(int format, int w, int h); int get_rot_output_format(int format); From 18e73bc5c74846fd1ab907539e70935362972394 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Wed, 7 Dec 2011 13:02:35 -0800 Subject: [PATCH 2/4] Display: Add libQcomUI Add libQComUI which is used to perform operations specified by SurfaceTextures. The operation currently supported by this library is SET_BUFFER_SIZE which deallocates and reallocates memory if the size allocated for the buffer does not match the size requested by the client. Change-Id: I370b94a91f5acf373f7040742aad7c2e7bb586fe --- Android.mk | 1 + libqcomui/Android.mk | 16 ++++ libqcomui/qcom_ui.cpp | 174 ++++++++++++++++++++++++++++++++++++++++++ libqcomui/qcom_ui.h | 72 +++++++++++++++++ 4 files changed, 263 insertions(+) create mode 100644 libqcomui/Android.mk create mode 100644 libqcomui/qcom_ui.cpp create mode 100644 libqcomui/qcom_ui.h diff --git a/Android.mk b/Android.mk index 373fbfc..565ddf1 100644 --- a/Android.mk +++ b/Android.mk @@ -1,4 +1,5 @@ #Enables the listed display HAL modules display-hals := libhwcomposer liboverlay libgralloc libgenlock libcopybit libtilerenderer +display-hals += libqcomui include $(call all-named-subdir-makefiles,$(display-hals)) diff --git a/libqcomui/Android.mk b/libqcomui/Android.mk new file mode 100644 index 0000000..270de84 --- /dev/null +++ b/libqcomui/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + qcom_ui.cpp + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + libmemalloc + +LOCAL_C_INCLUDES := $(TOP)/hardware/qcom/display/libgralloc +LOCAL_CFLAGS := -DLOG_TAG=\"libQcomUI\" +LOCAL_MODULE := libQcomUI +LOCAL_MODULE_TAGS := optional +include $(BUILD_SHARED_LIBRARY) diff --git a/libqcomui/qcom_ui.cpp b/libqcomui/qcom_ui.cpp new file mode 100644 index 0000000..9f843dd --- /dev/null +++ b/libqcomui/qcom_ui.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +using gralloc::IMemAlloc; +using gralloc::IonController; +using gralloc::alloc_data; +using android::sp; + +namespace { + + static android::sp sAlloc = 0; + + int reallocate_memory(native_handle_t *buffer_handle, int mReqSize, int usage) + { + int ret = 0; + if (sAlloc == 0) { + sAlloc = gralloc::IAllocController::getInstance(true); + } + if (sAlloc == 0) { + LOGE("sAlloc is still NULL"); + return -EINVAL; + } + + // Dealloc the old memory + private_handle_t *hnd = (private_handle_t *)buffer_handle; + sp memalloc = sAlloc->getAllocator(hnd->flags); + ret = memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd); + + if (ret) { + LOGE("%s: free_buffer failed", __FUNCTION__); + return -1; + } + + // Realloc new memory + alloc_data data; + data.base = 0; + data.fd = -1; + data.offset = 0; + data.size = mReqSize; + data.align = getpagesize(); + data.uncached = true; + int allocFlags = usage; + + switch (hnd->format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: + case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED^HAL_PIXEL_FORMAT_INTERLACE): { + data.align = 8192; + } break; + default: break; + } + ret = sAlloc->allocate(data, allocFlags, 0); + if (ret == 0) { + hnd->fd = data.fd; + hnd->base = (int)data.base; + hnd->offset = data.offset; + hnd->size = data.size; + } else { + LOGE("%s: allocate failed", __FUNCTION__); + return -EINVAL; + } + return ret; + } +}; // ANONYNMOUS NAMESPACE + +/* + * Gets the number of arguments required for this operation. + * + * @param: operation whose argument count is required. + * + * @return -EINVAL if the operation is invalid. + */ +int getNumberOfArgsForOperation(int operation) { + int num_args = -EINVAL; + switch(operation) { + case NATIVE_WINDOW_SET_BUFFERS_SIZE: + num_args = 1; + break; + default: LOGE("%s: invalid operation(0x%x)", __FUNCTION__, operation); + break; + }; + return num_args; +} + +/* + * Checks if the format is supported by the GPU. + * + * @param: format to check + * + * @return true if the format is supported by the GPU. + */ +bool isGPUSupportedFormat(int format) { + bool isSupportedFormat = true; + switch(format) { + case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED^HAL_PIXEL_FORMAT_INTERLACE): + case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED|HAL_3D_OUT_SIDE_BY_SIDE + |HAL_3D_IN_SIDE_BY_SIDE_R_L): + case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED|HAL_3D_OUT_SIDE_BY_SIDE + |HAL_3D_IN_SIDE_BY_SIDE_L_R): + isSupportedFormat = false; + break; + default: break; + } + return isSupportedFormat; +} + +/* + * Function to check if the allocated buffer is of the correct size. + * Reallocate the buffer with the correct size, if the size doesn't + * match + * + * @param: handle of the allocated buffer + * @param: requested size for the buffer + * @param: usage flags + * + * return 0 on success + */ +int checkBuffer(native_handle_t *buffer_handle, int size, int usage) +{ + // If the client hasn't set a size, return + if (0 == size) { + return 0; + } + + // Validate the handle + if (private_handle_t::validate(buffer_handle)) { + LOGE("%s: handle is invalid", __FUNCTION__); + return -EINVAL; + } + + // Obtain the private_handle from the native handle + private_handle_t *hnd = reinterpret_cast(buffer_handle); + if (hnd->size < size) { + return reallocate_memory(hnd, size, usage); + } + + return 0; +} + + + + diff --git a/libqcomui/qcom_ui.h b/libqcomui/qcom_ui.h new file mode 100644 index 0000000..b55ff4a --- /dev/null +++ b/libqcomui/qcom_ui.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef INCLUDE_LIBQCOM_UI +#define INCLUDE_LIBQCOM_UI + +#include + +/* + * Qcom specific Native Window perform operations + */ +enum { + NATIVE_WINDOW_SET_BUFFERS_SIZE = 0x10000000, +}; + +/* + * Function to check if the allocated buffer is of the correct size. + * Reallocate the buffer with the correct size, if the size doesn't + * match + * + * @param: handle of the allocated buffer + * @param: requested size for the buffer + * @param: usage flags + * + * return 0 on success + */ +int checkBuffer(native_handle_t *buffer_handle, int size, int usage); + +/* + * Checks if the format is supported by the GPU. + * + * @param: format to check + * + * @return true if the format is supported by the GPU. + */ +bool isGPUSupportedFormat(int format); + +/* + * Gets the number of arguments required for this operation. + * + * @param: operation whose argument count is required. + * + * @return -EINVAL if the operation is invalid. + */ +int getNumberOfArgsForOperation(int operation); +#endif // INCLUDE_LIBQCOM_UI From be32078a404a7bf6b326bcbacbc260900542f87b Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 9 Dec 2011 15:30:49 -0800 Subject: [PATCH 3/4] libQcomUI: Add support for updating the buffer geometry Add support for updating the buffer geometry without any reallocation of memory. The buffer geometry is updated in the GraphicBuffer as well as in the buffer handle. Change-Id: I3fdb4f6a737277ab63fcbdb42e9c955ea7471760 --- libqcomui/Android.mk | 5 +-- libqcomui/qcom_ui.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++- libqcomui/qcom_ui.h | 42 ++++++++++++++++++++++- 3 files changed, 123 insertions(+), 4 deletions(-) diff --git a/libqcomui/Android.mk b/libqcomui/Android.mk index 270de84..2b786d9 100644 --- a/libqcomui/Android.mk +++ b/libqcomui/Android.mk @@ -7,9 +7,10 @@ LOCAL_SRC_FILES := \ LOCAL_SHARED_LIBRARIES := \ libutils \ libcutils \ - libmemalloc + libmemalloc \ + libui -LOCAL_C_INCLUDES := $(TOP)/hardware/qcom/display/libgralloc +LOCAL_C_INCLUDES := $(TOP)/hardware/qcom/display/libgralloc \ LOCAL_CFLAGS := -DLOG_TAG=\"libQcomUI\" LOCAL_MODULE := libQcomUI LOCAL_MODULE_TAGS := optional diff --git a/libqcomui/qcom_ui.cpp b/libqcomui/qcom_ui.cpp index 9f843dd..df82cae 100644 --- a/libqcomui/qcom_ui.cpp +++ b/libqcomui/qcom_ui.cpp @@ -108,6 +108,9 @@ int getNumberOfArgsForOperation(int operation) { case NATIVE_WINDOW_SET_BUFFERS_SIZE: num_args = 1; break; + case NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY: + num_args = 3; + break; default: LOGE("%s: invalid operation(0x%x)", __FUNCTION__, operation); break; }; @@ -169,6 +172,81 @@ int checkBuffer(native_handle_t *buffer_handle, int size, int usage) return 0; } - +/* + * Checks if memory needs to be reallocated for this buffer. + * + * @param: Geometry of the current buffer. + * @param: Required Geometry. + * @param: Geometry of the updated buffer. + * + * @return True if a memory reallocation is required. + */ +bool needNewBuffer(const qBufGeometry currentGeometry, + const qBufGeometry requiredGeometry, + const qBufGeometry updatedGeometry) +{ + // If the current buffer info matches the updated info, + // we do not require any memory allocation. + if (updatedGeometry.width && updatedGeometry.height && + updatedGeometry.format) { + return false; + } + if (currentGeometry.width != requiredGeometry.width || + currentGeometry.height != requiredGeometry.height || + currentGeometry.format != requiredGeometry.format) { + // Current and required geometry do not match. Allocation + // required. + return true; + } + return false; +} + +/* + * Update the geometry of this buffer without reallocation. + * + * @param: buffer whose geometry needs to be updated. + * @param: Updated width + * @param: Updated height + * @param: Updated format + */ +int updateBufferGeometry(sp buffer, const qBufGeometry updatedGeometry) +{ + if (buffer == 0) { + LOGE("%s: graphic buffer is NULL", __FUNCTION__); + return -EINVAL; + } + + if (!updatedGeometry.width || !updatedGeometry.height || + !updatedGeometry.format) { + // No update required. Return. + return 0; + } + if (buffer->width == updatedGeometry.width && + buffer->height == updatedGeometry.height && + buffer->format == updatedGeometry.format) { + // The buffer has already been updated. Return. + return 0; + } + + // Validate the handle + if (private_handle_t::validate(buffer->handle)) { + LOGE("%s: handle is invalid", __FUNCTION__); + return -EINVAL; + } + buffer->width = updatedGeometry.width; + buffer->height = updatedGeometry.height; + buffer->format = updatedGeometry.format; + private_handle_t *hnd = (private_handle_t*)(buffer->handle); + if (hnd) { + hnd->width = updatedGeometry.width; + hnd->height = updatedGeometry.height; + hnd->format = updatedGeometry.format; + } else { + LOGE("%s: hnd is NULL", __FUNCTION__); + return -EINVAL; + } + + return 0; +} diff --git a/libqcomui/qcom_ui.h b/libqcomui/qcom_ui.h index b55ff4a..0b78f47 100644 --- a/libqcomui/qcom_ui.h +++ b/libqcomui/qcom_ui.h @@ -31,12 +31,31 @@ #define INCLUDE_LIBQCOM_UI #include +#include + +using android::sp; +using android::GraphicBuffer; /* * Qcom specific Native Window perform operations */ enum { - NATIVE_WINDOW_SET_BUFFERS_SIZE = 0x10000000, + NATIVE_WINDOW_SET_BUFFERS_SIZE = 0x10000000, + NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY = 0x20000000, +}; + +/* + * Structure to hold the buffer geometry + */ +struct qBufGeometry { + int width; + int height; + int format; + void set(int w, int h, int f) { + width = w; + height = h; + format = f; + } }; /* @@ -69,4 +88,25 @@ bool isGPUSupportedFormat(int format); * @return -EINVAL if the operation is invalid. */ int getNumberOfArgsForOperation(int operation); + +/* + * Checks if memory needs to be reallocated for this buffer. + * + * @param: Geometry of the current buffer. + * @param: Required Geometry. + * @param: Geometry of the updated buffer. + * + * @return True if a memory reallocation is required. + */ +bool needNewBuffer(const qBufGeometry currentGeometry, + const qBufGeometry requiredGeometry, + const qBufGeometry updatedGeometry); + +/* + * Update the geometry of this buffer without reallocation. + * + * @param: buffer whose geometry needs to be updated. + * @param: Updated buffer geometry + */ +int updateBufferGeometry(sp buffer, const qBufGeometry bufGeometry); #endif // INCLUDE_LIBQCOM_UI From 8d7ff87f5c874ea1af716379e9bfbc485ef869ec Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Sun, 11 Dec 2011 15:25:13 -0800 Subject: [PATCH 4/4] libQcomUI: Add support for qcom specific layer flags. Add support for updating the qcom specific layer flags. Add support for getting the per frame HWC flags based on the layer flags. Change-Id: I5f7759a6a7fae6d4f70dd26f380a9b08e48e9475 --- libqcomui/qcom_ui.cpp | 41 ++++++++++++++++++++++++++++++++++++++ libqcomui/qcom_ui.h | 46 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/libqcomui/qcom_ui.cpp b/libqcomui/qcom_ui.cpp index df82cae..9de00e7 100644 --- a/libqcomui/qcom_ui.cpp +++ b/libqcomui/qcom_ui.cpp @@ -249,4 +249,45 @@ int updateBufferGeometry(sp buffer, const qBufGeometry updatedGeo return 0; } +/* + * Updates the flags for the layer + * + * @param: Attribute + * @param: Identifies if the attribute was enabled or disabled. + * + * @return: -EINVAL if the attribute is invalid + */ +int updateLayerQcomFlags(eLayerAttrib attribute, bool enable, int& currentFlags) +{ + int ret = 0; + switch (attribute) { + case LAYER_UPDATE_STATUS: { + if (enable) + currentFlags |= LAYER_UPDATING; + else + currentFlags &= ~LAYER_UPDATING; + } break; + default: LOGE("%s: invalid attribute(0x%x)", __FUNCTION__, attribute); + break; + } + return ret; +} + +/* + * Gets the per frame HWC flags for this layer. + * + * @param: current hwcl flags + * @param: current layerFlags + * + * @return: the per frame flags. + */ +int getPerFrameFlags(int hwclFlags, int layerFlags) { + int flags = hwclFlags; + if (layerFlags & LAYER_UPDATING) + flags &= ~HWC_LAYER_NOT_UPDATING; + else + flags |= HWC_LAYER_NOT_UPDATING; + + return flags; +} diff --git a/libqcomui/qcom_ui.h b/libqcomui/qcom_ui.h index 0b78f47..6744edf 100644 --- a/libqcomui/qcom_ui.h +++ b/libqcomui/qcom_ui.h @@ -44,6 +44,30 @@ enum { NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY = 0x20000000, }; +/* + * Layer Attributes + */ +enum eLayerAttrib { + LAYER_UPDATE_STATUS, +}; + +/* + * Layer Flags + */ +enum { + LAYER_UPDATING = 1<<0, +}; + +/* + * Flags set by the layer and sent to HWC + */ +enum { + HWC_LAYER_NOT_UPDATING = 0x00000002, + HWC_USE_ORIGINAL_RESOLUTION = 0x10000000, + HWC_DO_NOT_USE_OVERLAY = 0x20000000, + HWC_COMP_BYPASS = 0x40000000, +}; + /* * Structure to hold the buffer geometry */ @@ -109,4 +133,26 @@ bool needNewBuffer(const qBufGeometry currentGeometry, * @param: Updated buffer geometry */ int updateBufferGeometry(sp buffer, const qBufGeometry bufGeometry); + +/* + * Updates the flags for the layer + * + * @param: Attribute + * @param: Identifies if the attribute was enabled or disabled. + * @param: current Layer flags. + * + * @return: Flags for the layer + */ +int updateLayerQcomFlags(eLayerAttrib attribute, bool enable, int& currentFlags); + +/* + * Gets the per frame HWC flags for this layer. + * + * @param: current hwcl flags + * @param: current layerFlags + * + * @return: the per frame flags. + */ +int getPerFrameFlags(int hwclFlags, int layerFlags); + #endif // INCLUDE_LIBQCOM_UI