/* * Copyright Samsung Electronics Co.,LTD. * Copyright (C) 2016 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 __HARDWARE_EXYNOS_ACRYLIC_H__ #define __HARDWARE_EXYNOS_ACRYLIC_H__ #include #include #include #include #include /* basic primitives */ #define MAX_HW2D_PLANES 4 /* * Structure to express 2-dimensional coordinates. * Invented to pass or to return two values in a single word */ typedef struct hw2d_coord { int16_t hori; int16_t vert; void swap() { int16_t tmp = hori; hori = vert; vert = tmp; } } hw2d_coord_t; /* * Structure to express a rectangle in a 2-dimensional grid. * Invented to pass or to return four values in a single 64-bit word */ typedef struct hw2d_rect { hw2d_coord_t pos; hw2d_coord_t size; } hw2d_rect_t; /* * Structure to express the capability of HW 2D Accelerators */ struct stHW2DCapability { /* maximum magnification with filter applied */ hw2d_coord_t max_upsampling_num; /* maximum minification factor with filter applied */ hw2d_coord_t max_downsampling_factor; /* maximum maginifcation without filter applied */ hw2d_coord_t max_upsizing_num; /* maximum minification factor without filter applied */ hw2d_coord_t max_downsizing_factor; /* the smallest source image size the HW can process */ hw2d_coord_t min_src_dimension; /* the largest source image size the HW can process */ hw2d_coord_t max_src_dimension; /* the smallest output image size the HW can process */ hw2d_coord_t min_dst_dimension; /* the largest output image size the HW can process */ hw2d_coord_t max_dst_dimension; /* * the restriction of the alignments of the numbers of pixels * in both of horizontal and vertical direction */ hw2d_coord_t min_pix_align; /* * The number of repeats of rescaling that the compositor supports. Note * that this is not the capability of the driver and H/W but the capability. * of the compositor(Acrylic). * If the driver and H/W supports rescaling, it is 0. If the compositor is * capable of running the H/W twice to overcome the minification restriction, * it is then 1. */ int16_t rescaling_count; /* * the compositing mode that the HW 2D supports. * should be combination of the values of HW2DCapability::blend_ops_t. */ uint32_t compositing_mode; /* * the geometric transformation in the 2-dimensional coordinate. * should be combination of the values of HW2DCapability::transform_t. */ uint32_t transform_type; /* * the capabilities of HW. The value is the combination of the values of * HW2DCapability::feature_t. */ uint32_t auxiliary_feature; /* * the number of color formats supported by HW 2D. * it is also the number of elements in pixformats array. */ unsigned int num_formats; /* * the number of color spaces supported by HW 2D. * it is also the number of elements in dataspaces array. */ unsigned int num_dataspaces; /* * the number of source images that HW 2D can process. */ unsigned int max_layers; /* * the array of color formats that are supported by HW 2D. the values should * be selected from the definitions in and exynos_formats.h. */ uint32_t *pixformats; /* * the array of color spaces that are supported by HW 2D. the values should * be selected from the definitions in . */ int *dataspaces; /* * the restriction of the alignments of the base addresses of buffers of images. */ size_t base_align; }; /* * HW2DCapability - Description of the capability of HW 2D. */ class HW2DCapability { public: /* * the values to indicate the capabilities of geometric transformations * supported by HW 2D accelerators. */ enum transform_t { TRANSFORM_FLIP_H = 1, /* horizontal flip: (symmetrical displacement by x = -x, y = y) */ TRANSFORM_FLIP_V = 2, /* vertical flip: (symmetrical displacement by x = x, y = -y) */ TRANSFORM_FLIP_HV = 3, /* horizontal flip then vertical flip */ TRANSFORM_ROT_90 = 4, /* clockwise rotation by 90 degree */ TRANSFORM_ROT_180 = 8, /* clockwise rotation by 180 degree */ TRANSFORM_ROT_270 = 16, /* clockwise rotation by 270 degree */ TRANSFORM_ROT_ALL = 28, /* bitmask to select rotation degrees */ TRANSFORM_ALL = 31 /* bitmask to select the correct bits */ }; /* * the values to indicate the capabilities of layer compositing * supported by HW 2D accelerators. * Sc: Source color, Dc: Destination(background) color, * Sa: Source alpha, Pa: Plane alpha */ enum blend_ops_t { BLEND_NONE = 1, /* Sc * 1 + Dc * 0 */ BLEND_SRC_COPY = 2, /* Sc * 1 * Pa + Dc * (1 - Sa) */ BLEND_SRC_OVER = 4, /* Sc * Sa * Pa + Dc * (1 - Sa) */ }; /* * The values to indicate the capabilities of 2D H/W. The capabilities * listed here shows if a function is supported or not. */ enum feature_t { FEATURE_PLANE_ALPHA = 1 << 0, FEATURE_AFBC_ENCODE = 1 << 4, FEATURE_AFBC_DECODE = 1 << 5, FEATURE_UORDER_READ = 1 << 6, FEATURE_UORDER_WRITE = 1 << 7, FEATURE_OTF_READ = 1 << 8, FEATURE_OTF_WRITE = 1 << 9, FEATURE_SOLIDCOLOR = 1 << 10, }; enum { RESAMPLING_FRACTION_BITS = 20 }; HW2DCapability(const stHW2DCapability &cap): mCap(cap) { } /* * returns the bitmask of supporting flip directions * the returned value is the combination of the values of transform_t. */ transform_t supportedFlip() const { return static_cast(mCap.transform_type & TRANSFORM_FLIP_HV); } /* * returns the bitmask of supporting rotation degrees * the returned value is the combination of the values of transform_t. */ transform_t supportedRotation() const { return static_cast(mCap.transform_type & TRANSFORM_ROT_ALL); } /* * returns the pair of the maximum maginifcation * in the horizontal and vertical direction with filter applied */ hw2d_coord_t supportedMaxMagnification() const { return mCap.max_upsampling_num;} /* * returns the pair of the maximum minifcation factor * in the horizontal and vertical direction with filter applied */ hw2d_coord_t supportedMinMinification() const { return mCap.max_downsampling_factor;} /* * returns the pair of the maximum maginifcation * in the horizontal and vertical direction without filter applied */ hw2d_coord_t supportedMaxEnlarging() const { return mCap.max_upsizing_num;} /* * returns the pair of the maximum minifcation factor * in the horizontal and vertical direction without filter applied */ hw2d_coord_t supportedMinDecimation() const { return mCap.max_downsizing_factor;} /* * returns the bitmask of supporting compositing modes * The returned value is the combination of the value sof blend_ops_t. */ uint32_t supportedCompositingMode() const { return mCap.compositing_mode; } /* * returns the alignment restriction of HW 2D in the base memory address. */ size_t supportedBaseAlign() const { return mCap.base_align; } /* * returns the maximum number of horizontal and vertical pixels * of the source images that HW 2D can process */ hw2d_coord_t supportedMaxSrcDimension() const { return mCap.max_src_dimension; } /* * returns the minimum number of horizontal and vertical pixels * of the source images that HW 2D can process */ hw2d_coord_t supportedMinSrcDimension() const { return mCap.min_src_dimension; } /* * returns the maximum number of horizontal and vertical pixels * of the output image that HW 2D can process */ hw2d_coord_t supportedMaxDstDimension() const { return mCap.max_dst_dimension; } /* * returns the minimum number of horizontal and vertical pixels * of the output image that HW 2D can process */ hw2d_coord_t supportedMinDstDimension() const { return mCap.min_dst_dimension; } /* * returns the alignment restriction of the number of horizontal * and vertical pixels that HW 2D can process */ hw2d_coord_t supportedDimensionAlign() const { return mCap.min_pix_align; } /* * returns the number of source images that HW 2D can composit */ unsigned int maxLayerCount() const { return mCap.max_layers; } /* * study if the given format is supported by the HW 2D */ bool isFormatSupported(uint32_t fmt) const { for (unsigned int i = 0; i < mCap.num_formats; i++) if (mCap.pixformats[i] == fmt) return true; return false; } /* * study if the given colorspace is supported by HW 2D */ bool isDataspaceSupported(int dataspace) const { // discard transfer function information because it is required during display dataspace &= ~HAL_DATASPACE_TRANSFER_MASK; for (unsigned int i = 0; i < mCap.num_dataspaces; i++) if (mCap.dataspaces[i] == dataspace) return true; return false; } /* * convert the transformation mask in transform_type into the values * that Android Graphics HAL understands. */ uint32_t getHWCTransformMask() const { uint32_t mask = 0; if (mCap.transform_type & TRANSFORM_FLIP_H) mask |= HAL_TRANSFORM_FLIP_H; if (mCap.transform_type & TRANSFORM_FLIP_V) mask |= HAL_TRANSFORM_FLIP_V; if (mCap.transform_type & TRANSFORM_ROT_90) mask |= HAL_TRANSFORM_ROT_90; if (mCap.transform_type & TRANSFORM_ROT_180) mask |= HAL_TRANSFORM_ROT_180; if (mCap.transform_type & TRANSFORM_ROT_270) mask |= HAL_TRANSFORM_ROT_270; return mask; } /* * discover if the given feature that is defined in feature_t is supported. */ bool isFeatureSupported(uint32_t feature) const { return !!(mCap.auxiliary_feature & feature); } /* * study if the given horizontal resolution change from @from into @to is * supported by HW 2D */ bool supportedHResampling(int16_t from, int16_t to, int16_t resamping_count = 1) const { return supportedResampling(from, to, mCap.max_upsampling_num.hori * resamping_count, mCap.max_downsampling_factor.hori * resamping_count); } /* * study if the given vertical resolution change from @from into @to is * supported by HW 2D */ bool supportedVResampling(int16_t from, int16_t to, int16_t resamping_count = 1) const { return supportedResampling(from, to, mCap.max_upsampling_num.vert * resamping_count, mCap.max_downsampling_factor.vert * resamping_count); } /* * study if the given resampling from @from to @to is supported by HW 2D compositor * implementation. */ bool supportedResampling(hw2d_coord_t from, hw2d_coord_t to, uint32_t transform) const { int count = supportedRescalingCount(); if (!!(transform & HAL_TRANSFORM_ROT_90)) to.swap(); return supportedHResampling(from.hori, to.hori, count) && supportedVResampling(from.vert, to.vert, count); } /* * study if the given resampling from @from to @to is supported by HW 2D */ bool supportedHWResampling(hw2d_coord_t from, hw2d_coord_t to, uint32_t transform) const { if (!!(transform & HAL_TRANSFORM_ROT_90)) to.swap(); return supportedHResampling(from.hori, to.hori, 1) && supportedVResampling(from.vert, to.vert, 1); } /* * study if the given number of horizontal pixels (@from) can be changed * to @to by HW 2D */ bool supportedHResizing(int16_t from, int16_t to) const { return supportedResizing(from, to, mCap.max_upsizing_num.hori, mCap.max_downsizing_factor.hori); } /* * study if the given number of vertical pixels (@from) can be changed * to @to by HW 2D */ bool supportedVResizing(int16_t from, int16_t to) const { return supportedResizing(from, to, mCap.max_upsizing_num.vert, mCap.max_downsizing_factor.vert); } /* * study if the given resizing from @from to @to is supported by HW 2D compositor * implementation. */ bool supportedResizing(hw2d_coord_t from, hw2d_coord_t to, uint32_t transform) const { if (!!(transform & HAL_TRANSFORM_ROT_90)) to.swap(); return supportedHResizing(from.hori, to.hori) && supportedVResizing(from.vert, to.vert); } /* * study the number rescaling by the compositor for a layer * 1 if the compositor does not repeat the scaling. 2 if the compositor * repeat the scaling once. * Note that the return value of supportedRescalingCount() is the one * incremented from the struct stHW2DCapability.rescaling_count. */ int supportedRescalingCount() const { return mCap.rescaling_count + 1; } private: bool supportedResampling(int16_t from, int16_t to, int16_t upfactor, int16_t downfactor) const { int64_t factor = static_cast(from); factor <<= RESAMPLING_FRACTION_BITS; factor /= to; if (factor > (static_cast(downfactor) << RESAMPLING_FRACTION_BITS)) return false; // @upfactor is a reciprocal number of an upsampling factor if (factor < ((1 << RESAMPLING_FRACTION_BITS) / static_cast(upfactor))) return false; return true; } bool supportedResizing(int16_t from, int16_t to, int16_t upfactor, int16_t downfactor) const { if ((from < to) && (upfactor == 0)) return true; if ((from > to) && (downfactor == 0)) return true; return supportedResampling(from, to, upfactor, downfactor); } const stHW2DCapability &mCap; }; class Acrylic; /* * AcrylicCanvas - Description of an image and its buffers * * It includes the entire image area and how the image is stored in the memory, * where it is stored and the buffer synchronization objects called Fence. * AcrylicCanvas contains the following attributes: * - image dimension: number of horizontal and vertical pixels * - color format of the image * - colorspace of the image * - the identifiers of the image buffers (userptr or dmabuf) * * Creation of AcrylicCanvas by new operator is prohibited. The only way to * create an instance of AcrylicCavans is to call Acrylic::createLayer(). */ class AcrylicCanvas { friend class Acrylic; public: /* * The attributes of the image described by AcrylicCanvas: * The attributes are bit masks and therefore combination of them may be * also required. * - ATTR_NONE: indicates no special attributes are specified * - ATTR_PROTECTED: the buffer of the image is protected. Reading or * writing to the buffer of the image is prohibited. * - ATTR_COMPRESSED: the image is or is to be stored in a compressed form. * e.g. AFBC * - ATTR_UORDER: the image data is written in U-order instead of raster-scan order. * U-order memory access by GPU helps the BUS efficiency. * - ATTR_OTF: The image buffer is hard-wired. If this attribute is given, libacryl * ignores the buffer configuration to the canvas. * - ATTR_SOLIDCOLOR : The image buffer is empty and should be filled with one RGBA value by H/W. */ enum layer_attr_t { ATTR_NONE = 0, ATTR_PROTECTED = 1, ATTR_COMPRESSED = 2, ATTR_UORDER = 4, ATTR_OTF = 8, ATTR_SOLIDCOLOR = 16, ATTR_ALL_MASK = 0x1F }; /* * Describes how the buffer of the image is identified. * - MT_DMABUF: the buffer is identified by an open file descriptor that is * exported by dmabuf. * - MT_USERPTR: the buffer is identified by a memory address that is valid * in the current process. Usally it is a bug if mAttributes * has ATTR_PROTECTED whlie mMemoryType is MT_USERPTR. * - MT_EMTPY : the buffer is empty such as hare-wired buffer or colorfill layer. */ enum memory_type { MT_DMABUF = 1, MT_USERPTR = 2, MT_EMPTY = 3 }; /* * Indicates the configured or modified settings * - SETTING_TYPE: Image format and color space information is configured by users. * - SETTING_BUFFER: Image buffer information is configured by users. * - SETTING_DIMENSION: Image dimension information is configured by users. * - SETTING_TYPE_MODIFIED: Image format and color space information is configured * by users and it is not applied to HW yet. * - SETTING_BUFFER_MODIFIED: Image buffer information is configured by users and * it is not applied to HW yet. * - SETTING_DIMENSION_MODIFIED: Image dimension information is configured by users * and it is not applied to HW yet. */ enum setting_check_t { SETTING_TYPE = 1, SETTING_BUFFER = 2, SETTING_DIMENSION = 4, SETTING_MASK = SETTING_TYPE | SETTING_BUFFER | SETTING_DIMENSION, SETTING_TYPE_MODIFIED = 16, SETTING_BUFFER_MODIFIED = 32, SETTING_DIMENSION_MODIFIED = 64, SETTIMG_MODIFIED_MASK = SETTING_TYPE_MODIFIED | SETTING_BUFFER_MODIFIED | SETTING_DIMENSION_MODIFIED, }; /* * MEMBER FUNCTIONS FOR THE USERS */ /* * Configure the dimension of the image */ virtual bool setImageDimension(int32_t width, int32_t height); /* * Find the dimension of the image configured to AcyrilicCanvas */ hw2d_coord_t getImageDimension() { return mImageDimension; } /* * Configure the image color format and color space * You should configure the correct colorspace if you want to change the * the image is YCbCr and the target image is RGB because the brightness * of the pixel data encoded in YCbCr is generated from various colorspaces * including BT.601, BT.709(sRGB) and BT.2020. If the YCbCr image is a frame * of a moving picture, we should likely consider the 1/16 headroom and * footroom. Generally BT.601, BT.709 and BT.2020 have footroom and headroom * while JFIF(JPEG, SRGB) does not have. */ bool setImageType(uint32_t fmt, int dataspace); /* * Configure color fill layer that fill only one RGBA color without actual buffer. * Note that this successes if the compositor supports FEATURE_SOLIDCOLOR. */ bool setImageBuffer(int a, int r, int g, int b, uint32_t attr = ATTR_NONE); /* * Configure the image buffer of dmabuf type. */ bool setImageBuffer(int fd[MAX_HW2D_PLANES], size_t len[MAX_HW2D_PLANES], off_t offset[MAX_HW2D_PLANES], int num_buffers, int fence = -1, uint32_t attr = ATTR_NONE); /* * Configure the image buffer of dmabuf type. * This does not receives a parameter 'offset' compared to the above * setImageBuffer(). The latter type of setImageBuffer() is provided to * provide convenience to the users because offsets are mostly zero. */ bool setImageBuffer(int fd[MAX_HW2D_PLANES], size_t len[MAX_HW2D_PLANES], int num_buffers, int fence = -1, uint32_t attr = ATTR_NONE) { off_t offset[MAX_HW2D_PLANES] = {0, 0, 0}; return setImageBuffer(fd, len, offset, num_buffers, fence, attr); } /* * Configure the image buffer of userptr type. * Note that you cannot pass a fence if the buffer type is userptr because * userptr buffer is not shareable between processes and devices. */ bool setImageBuffer(void *addr[MAX_HW2D_PLANES], size_t len[MAX_HW2D_PLANES], int num_buffers, uint32_t attr = ATTR_NONE); /* * Configure the image buffer is hard-wired which means that the buffer is always * prepared in the compositor H/W. * Note that this successes if the compositor supports FEATURE_OTF_READ or FEATURE_OTF_WRITE. */ bool setImageOTFBuffer(uint32_t attr = AcrylicCanvas::ATTR_NONE); /* * Configure the fence. setFence() overwrites the fence specified by * setImageBuffer(). */ void setFence(int fence); /* * Called by the implementations of Acyrlic to determine if all required * configurations are completed. */ bool isSettingOkay() { return (mSettingFlags & SETTING_MASK) == (SETTING_TYPE | SETTING_BUFFER | SETTING_DIMENSION); } /* * MEMBER FUNCTIONS FOR THE IMPLEMENTATIONS of Acrylic */ /* * Determine if the buffer is protected. If the buffer or the image is * protected, the driver of HW 2D should specially care the buffer and the * processing involving the buffer. */ bool isProtected() { return !!(mAttributes & ATTR_PROTECTED); } /* * Determine if the image in the buffer is or should be in a compressed form. */ bool isCompressed() { return !!(mAttributes & ATTR_COMPRESSED); } /* * Study if the image is or should be written in U-Order for accelerated * graphic processing instead of raster-scan order. */ bool isUOrder() { return !!(mAttributes & ATTR_UORDER); } /* * Study if the canvas buffer is hard-wired. */ bool isOTF() { return !!(mAttributes & ATTR_OTF); } /* * Study if the image is filled with solid color. */ bool isSolidColor() { return !!(mAttributes & ATTR_SOLIDCOLOR); } /* * Obtain the acquire fence of the buffer. */ int getFence() const { return mFence; } /* * Invalidate the confgured acquire fence without destryoing(close()) it */ void clearFence() { mFence = -1; } /* * Obtain the image color format */ uint32_t getFormat() { return mPixFormat; } /* * Obtain the color space information */ int getDataspace() { return mDataSpace; } /* * Obtain the buffer type whether the buffer is MT_USERPTR or MT_DMABUF */ memory_type getBufferType() { return mMemoryType; } /* * Obtain the number of buffers. * The parameter 'index' of the following member functions including * getDmabuf(), getUserptr(), getOffset(), getBufferLength() should be * smaller than the return value of getBufferCount(). Otherwise, you will * get invalid memory area referenced. */ unsigned int getBufferCount() { return mNumBuffers; } /* * Obtain the open file descriptor exported by dmabuf if the buffer type is * MT_DMABUF */ int getDmabuf(unsigned int index) { return (mMemoryType == MT_DMABUF) ? m.mBufferFd[index] : -1; } /* * Obtain the buffer address if the buffer type is MT_USERPTR */ void *getUserptr(unsigned int index) { return (mMemoryType == MT_USERPTR) ? m.mBufferAddr[index] : NULL; } /* * Obtain the offset where the image is stored in the buffer if the buffer * type is MT_DMABUF */ uint32_t getOffset(unsigned int index) { return (mMemoryType == MT_DMABUF) ? mBufferOffset[index] : 0; } /* * Obtain the length of the buffer */ uint32_t getBufferLength(unsigned int index) { return mBufferLength[index]; } /* * Clear all modified states. It is called by the Acrylic implementations after * they executes their HWs */ void clearSettingModified() { unset(SETTING_TYPE_MODIFIED | SETTING_BUFFER_MODIFIED | SETTING_DIMENSION_MODIFIED); } /* * Obtain the flags that indicates the configuration status */ uint32_t getSettingFlags() { return mSettingFlags; } /* * Obtain the solid color combined by 8bit of A, R, G, B */ uint32_t getSolidColor() { return mSolidColor; } protected: enum canvas_type_t { CANVAS_SOURCE, CANVAS_TARGET, }; Acrylic *mCompositor; AcrylicCanvas(Acrylic *compositor, canvas_type_t type = CANVAS_SOURCE); virtual ~AcrylicCanvas(); Acrylic *getCompositor() { return mCompositor; } void unset(uint32_t flag) { mSettingFlags &= ~flag; } void set(uint32_t flag) { mSettingFlags |= flag; } private: /* * called when Acrylic is being destroyed to inform AcrylicCanvas * that no Acrylic has a reference to it. */ void disconnectLayer() { mCompositor = NULL; } hw2d_coord_t mImageDimension; uint32_t mPixFormat; int mDataSpace; memory_type mMemoryType; union { void *mBufferAddr[MAX_HW2D_PLANES]; int mBufferFd[MAX_HW2D_PLANES]; } m; size_t mBufferLength[MAX_HW2D_PLANES]; uint32_t mBufferOffset[MAX_HW2D_PLANES]; int mNumBuffers; int mFence; // NOTE: this should be reset to -1 after Acrylic::execute() uint32_t mAttributes; uint32_t mSettingFlags; uint32_t mSolidColor; // [32:0] ARGB order. canvas_type_t mCanvasType; }; /* * AcrylicLayer - Description of compositing properties * as well as an image and its buffers * * AcrylicLayer extends the properties of AcrylicCanvas for compositing purpose. * It adds the following propertes to AcrylicCanvas: * - The rectangle region of interest in the image. It is usually called 'crop' * - The rectangle region to map the crop area in the target dimension. It is * usually called 'window'. If the width or the height of the window is * different from crop, resampling or resizing is invloved. * - How the input images are composited. Currently Acrylic supports only the * following opertions: * .HWC_BLENDING_NONE: The alpha channel in the image should be ignored * .HWC_BLENDING_PREMULT: The color brightness values are regardted as they * are multiplied with its alpha channel value * .HWC_BLENDING_COVERAGE: The alpha value of each pixel is multiplied with * the brighness of each pixel during compositing. * - How to transfrom the image into window: flip, rotation * - The order of input images to be stacked on the background * - The transparent level of the image. It is multiplied to every pixel * brightness values when compositing. The transparent level of the entire * image is also called 'plane alpha' or 'global alpha'. * * The default properties are: * - mImageRect: the entire image dimension. * - mTargetRect: the entire target dimension * - mBlendingMode: HWC_BLENDING_NONE * - mTransform: 0 (no flip, no rotation) * - mZOrder: 0 * - mPlaneAlpha: 1.0(255) * * Creation of AcrylicLayer by new operator is prohibited. The only way to * create an instance of AcrylicLayer is to call Acrylic::createLayer(). */ class AcrylicLayer: public AcrylicCanvas { friend class Acrylic; public: /* * The various/special attributes to the source images * - ATTR_NORESAMPLING: Force resize the image speicifed to the layer even * though the target image size is too small to apply * the interpolation filter correctly. */ enum composit_attr_t { ATTR_NORESAMPLING = 1, ATTR_ALL_MASK = 1}; virtual ~AcrylicLayer(); /* * MEMBER FUNCTIONS FOR THE USERS */ /* * Configure the compositing mode including the compositing operations, * plane alpha and z-order */ bool setCompositMode(uint32_t mode, uint8_t alpha = 0xFF, int z_order = 0); /* * Configure the crop, window, transformation and special compositing attributes. */ bool setCompositArea(hwc_rect_t &src_area, hwc_rect_t &out_area, uint32_t transform = 0, uint32_t attr = 0); /* * Configure the crop and transformation information. The window rect is * is regarded as the entire target dimension. */ bool setCompositArea(hwc_rect_t &src_area, uint32_t transform = 0, uint32_t attr = 0) { hwc_rect_t out_area = {0, 0, 0, 0}; return setCompositArea(src_area, out_area, transform, attr); } /* * Configure the dimension of the image. This function overrides * AcrylicCanvas::setImageDimension(). Once this function is called, the * crop rect, mImageRect reset to the entire image dimension configured * by this function. Note that the window, mTargetRect is not reset because * it is not dependent upon the image dimension. */ virtual bool setImageDimension(int32_t width, int32_t height); /* * Configure the source image area(crop) with the target rect and transform * untouched while setCompositArea() modifies source rect, target rect and * transform with the given arguments. */ bool setImageRect(hwc_rect_t &src_area) { hwc_rect_t out_area = { mTargetRect.pos.hori, mTargetRect.pos.vert, mTargetRect.pos.hori + mTargetRect.size.hori, mTargetRect.pos.vert + mTargetRect.size.vert }; return setCompositArea(src_area, out_area, mTransform); } /* * Configure the minimum liminance and the maximum luminance of the display * used in the HDR video mastering environment. It is spepcified in the * metatata of the HDR video contents. * @min: minimum luminance in 0.0001 cd/m^2 unit * @max: maximum luminance in 1 cd/m^2 unit * * The followings are the default values: * @min: 0 * @max: 100 (SDR) * * NOTE: * The configured video is treated as SDR until setMasterDisplayLuminance() * is called. It means that the target image is to be SDR. */ void setMasterDisplayLuminance(uint16_t min, uint16_t max); /* * Configure an opaque data associated to a layer * @data: pointer to data associated to this layer * @data_len: number of effective bytes pointed by @data * * The configured data is opaque to libacryl. It should be handled by the * implementations. How to specify and how to understand the data is just * contract between the user of a specific implementation and the implemtation. * The configured data is effective until the data is cleared by invoking * clearLayerData(). * The second argument @data_lan can be used for checking the contract. The * implementation and the users should decide the data structure delivered by * setLayerData(). If the data structure has fixed length, the implementation * can determine if the delivered data is correctly configured with comparing * @data_len and the expected size. */ void setLayerData(void *data, size_t data_len) { mLayerData = data; mLayerDataLen = data_len; } /* * Clears the configured layer data. */ void clearLayerData() { mLayerData = nullptr; mLayerDataLen = 0; } /* * MEMBER FUNCTIONS FOR THE IMPLEMENTATIONS of Acrylic */ /* * Optain the configured compositing mode */ uint32_t getCompositingMode() { return mBlendingMode; } /* * Obtain the z-order of the layer */ int32_t getZOrder() { return mZOrder; } /* * Obtain the plane alpha value of the layer */ uint8_t getPlaneAlpha() { return mPlaneAlpha; } /* * Obtain the crop region of the layer */ hw2d_rect_t getImageRect() { return mImageRect; } /* * Obtain the window region onto the background. If all four values are * zero, the window region should be regarded as the entire background * dimension. */ hw2d_rect_t getTargetRect() { return mTargetRect; } /* * Obtain the transform property of the layer */ uint32_t getTransform() { return mTransform; } /* * Obtain the special compositing attribute flags */ uint32_t getCompositAttr() { return mCompositAttr; } /* * Obtain the minimum luminance of the display of the mastering environment * of the video layer in the unit of 0.0001 cd/m^2. */ uint16_t getMinMasteringLuminance() { return mMinLuminance; } /* * Obtain the maximum luminance of the display of the mastering environment * of the video layer in the unit of 1 cd/m^2. */ uint16_t getMaxMasteringLuminance() { return mMaxLuminance; } /* * Copy the contents of @layer into the callee instance. * Note that the file descriptors of @layer are not duplicated. The caller * should care about that. Note also that importLayer() invalidates the * acquire fence of @layer because it is transferred to the callee. */ void importLayer(AcrylicLayer &layer, bool inherit_transform); /* * Store the given transit data to the instance. It is generated by the * implementations of Acrylic class. */ void storeTransit(void *transitData) { mTransitData = transitData; } /* * Retrieve the transit data from the instance. */ void *getTransit() { return mTransitData; } /* * Retrieve the layer opaque data. */ void *getLayerData() { return mLayerData; } size_t getLayerDataLength() { return mLayerDataLen; } private: AcrylicLayer(Acrylic *compositor); void *mTransitData; void *mLayerData; size_t mLayerDataLen; hw2d_rect_t mImageRect; hw2d_rect_t mTargetRect; uint32_t mBlendingMode; uint32_t mTransform; int32_t mZOrder; uint32_t mCompositAttr; uint16_t mMaxLuminance; // in nit uint16_t mMinLuminance; // in 0.0001 nit uint8_t mPlaneAlpha; }; class AcrylicPerformanceRequest; /* * DEPRECATED: * AcrylicFactory works as it did for now but it will be removed in the future * because new factory methods to create an instance of Acrylic is introduced: * use the followings instead of AcrylicFactory: * - Acrylic::createInstance() for a specific Acrylic backend * - Acrylic::createCompositor() to create the "default_compositor" * - Acrylic::createScaler() to create the "default_scaler" * * AcrylicFactory - The creator of Acrylic * * Users are prohibited to create an instance of Acrylic because the does not * have enough knowledge how to create. Instead, users should ask the factory * to create an instance of Acrylic with a special 'name'(spec) to identify a * specific HW 2D. */ class AcrylicFactory { public: AcrylicFactory() { }; ~AcrylicFactory() { }; /* * Creator of Acrylic instance */ static Acrylic *createAcrylic(const char *spec); }; /* * Acrylic - The type of the object for 2D compositing with HW 2D * * Acrylic executes HW 2D with the image information specified on AcrylicLayers * and AcrylicCanvas that are created by Acrylic. * To create an instance of Acrylic, you should use AcrylicFactory. */ class Acrylic { public: /* * Factory methods of an instance of Acrylic subclasses * createInstance() - create the instance exactly specified by @spec * createCompositor() - create an instance of HW 2D compositor defined in board definition * createScaler() - create an instance of image post processor defined in board definition * createBlter() - create an instance of H/W accelerator of bit block transfer defined in board definition */ static Acrylic *createInstance(const char *spec); static Acrylic *createCompositor(); static Acrylic *createScaler(); static Acrylic *createBlter(); Acrylic(const HW2DCapability &capability); virtual ~Acrylic(); /* * Create a new instance of AcrylicLayer. If the number of created * AcrylicLayer is already mCapability.maxLayerCount(), createLayer() * fails. * The caller of createLayer() should destroy the instance of AcrylicLayer * by itself. The instance of AcrylicLayer is only available while the * Acrylic that created it lives. If the Acrylic that created AcrylicLayer * has been destroyed, all configuration to AcrylicLayer have no effect. */ AcrylicLayer *createLayer(); /* * Obtain HW2DCapability object to study the capability fo HW 2D that the * Acrylic handles. */ const HW2DCapability &getCapabilities() { return mCapability; } /* * Configure the image dimension of the background. The background image * is not the input image with the lowest z-order but the target image in * this context. */ bool setCanvasDimension(int32_t width, int32_t height) { return mCanvas.setImageDimension(width, height); } /* * Configure the image color format and the address space of the target image */ bool setCanvasImageType(uint32_t fmt, int dataspace) { return mCanvas.setImageType(fmt, dataspace); } /* * Configure the buffers where to write the result (target) image. The * identifier of the buffer is a open file descriptor exported by dmabuf. * Users can also configure if the result image is in the compressed form * or to be protected from access by non-previliged users. */ bool setCanvasBuffer(int fd[MAX_HW2D_PLANES], size_t len[MAX_HW2D_PLANES], off_t offset[MAX_HW2D_PLANES], int num_buffers, int fence = -1, uint32_t attr = AcrylicCanvas::ATTR_NONE) { return mCanvas.setImageBuffer(fd, len, offset, num_buffers, fence, attr); } /* * Configure the buffers where to write the result (target) image. * This version ov setCanvasBuffer() is the same as the above version except * that this version does not require @offset as its argument. */ bool setCanvasBuffer(int fd[MAX_HW2D_PLANES], size_t len[MAX_HW2D_PLANES], int num_buffers, int fence = -1, uint32_t attr = AcrylicCanvas::ATTR_NONE) { return mCanvas.setImageBuffer(fd, len, num_buffers, fence, attr); } /* * Configure the buffers where to write the result (target) image. The * identifier of the buffer is a valid memory address in the address space * of the caller. AcrylicCanvas::ATTR_PROTECTED to @attr is not allowed * because userptr buffer should not be protected. */ bool setCanvasBuffer(void *addr[MAX_HW2D_PLANES], size_t len[MAX_HW2D_PLANES], int num_buffers, uint32_t attr = AcrylicCanvas::ATTR_NONE) { return mCanvas.setImageBuffer(addr, len, num_buffers, attr); } /* * Configure the target buffers as hard-wired. */ bool setCanvasOTF(uint32_t attr = AcrylicCanvas::ATTR_NONE) { return mCanvas.setImageOTFBuffer(attr); } /* * Configure the default background color and the opacity. It is effecitve * when the source images are not opaque or the source images does not fill * the entire target image buffer. * Configuring the default color makes the result image more deterministic. * NOTE that the value(brightness) of each color components and the opacity * are 16-bit wide. If your system supports 8-bit brightness, you should * shift the brightness value to the left in the amount of 8 bits. Again, * you should multiply the value of each color components and the opacity * with 256 (2^8) if your color system supports 8-bit brightness levels. */ void setDefaultColor(uint16_t red, uint16_t green, uint16_t blue, uint16_t alpha) { mBackgroundColor.R = red; mBackgroundColor.G = green; mBackgroundColor.B = blue; mBackgroundColor.A = alpha; mHasBackgroundColor = true; } /* * Cancel the configured default color values. */ void clearDefaultColor() { mHasBackgroundColor = false; } /* * Configures cofficients the tone mapper if the user of Acrylic wants to * overrides the default coefficients of the tone mapper for HDR display. * The coefficients are a two dimensional array of coefficients of x-axis * and y-axis. If no coefficient is configured, the default function of the * implemntation of Acrylic is used. It may be ether of gamma 2.2 for SDR, * gamma 2.6 for HDR. * The configured coefficients are not enabled if no layer has HDR video * because HDR processing is not enabled. */ virtual bool setHDRToneMapCoefficients(uint32_t *matrix[2], int num_elements); /* * Configure the minimum luminance and the maximum luminance of the target * display. * @min: minimum luminance in 0.0001 cd/m^2 unit * @max: maximum luminance in 1 cd/m^2 unit * * The following sare the default values: * @min: 0 * @max 100 (SDR) * * NOTE: * How to handle the target display luminance depends on the implementation * of Acrylic. An implementation does not refer to the configured target * display luminance while another implementation may us the taret display * luminance to choose its HDR conversion logic. */ inline void setTargetDisplayLuminance(uint16_t min, uint16_t max) { mMaxTargetLuminance = max; mMinTargetLuminance = min; } /* * Configure information of target display device. */ inline void setTargetDisplayInfo(void *data) { mTargetDisplayInfo = data; } /* * Run HW 2D. If @fence is not NULL and num_fences is not zero, execute() * fills the release fences to the array of @fence. The number of fences * filled by execute() is min(num_fences, mLayers.size()). If num_fences is * larger than mLayers.size(), execute() fills -1 to the rest of the elements * of @fence. * execute() returns before HW 2D completes the processing, of course. */ virtual bool execute(int fence[], unsigned int num_fences) = 0; /* * Run HW 2D. This version of execute() does not provides release fences. * If @handle is NULL, execute() does not return until HW 2D completes * the processng. If @handle is not NULL, execute() returns before HW 2D * completes and stores a value(handle) to @handle. Users can wait for HW 2D * to be finished with that handle. Users does not need to wait HW 2D. Then, * they sshould release the handle with releaseHandle(). */ virtual bool execute(int *handle = NULL) = 0; /* * Release @handle informed by execute() */ virtual void releaseHandle(int __attribute__((__unused__)) handle) { } /* * Wait HW 2D to finish the processing associated with @handle. The handle * is released after the wait completes. */ virtual bool waitExecution(int handle) = 0; /* * Return the last execution time of the H/W in micro seconds. * It is only vaild when the last call to execute() succeeded. */ virtual unsigned int getLaptimeUSec() { return 0; } /* * Configure the priority of the image processing tasks requested * to this compositor object. The default priority is -1 and the * highest priority is 15. If a user configure a priority outside * of the range between -1 and 15, the user will get failure. * How the priority to be applied is the implmentation specific. * prioritize() returns a negative value (-1) on failure. On successful, * prioritize() returns zero or a positive value. An implementation may * return a positive value to inform additional information. */ virtual int prioritize(int priority = -1); /* * Configure a value for guaranteeing quality of service in terms * of image processing performance. The types and ranges of the * value is not defined by libacryl but the end users including * HWC and the driver. libacryl just deliver the value to the * driver that the implementation of Acrylic is talking with. * If the implementation does not implement requestPerformanceQoS(), * calling requestPerformanceQoS() effects nothing. * The types, the size and the number of the parameters are defined * as required. They should be defined in acrylic_soc.h. */ virtual bool requestPerformanceQoS(AcrylicPerformanceRequest *request); /* * Called when an AcrylicLayer is being destroyed */ void removeLayer(AcrylicLayer *layer); /* * Obtains the instance AcrylicCanvas of the taret image. It is called by * the implementations of Acrylic and the test modules of Acrylic. The other * users of Acrylic do not need to call getCanvas(). Instead, consider * setCanvasDimension(), setCanvasImageType() and setCanvasBuffer(). */ AcrylicCanvas &getCanvas() { return mCanvas; } unsigned int layerCount() { return static_cast(mLayers.size()); } protected: /* * Called when an AcrylicLayer is destroyed. Unlike removeLayer(), * removeTransitData() is called whenever an AcrylicLayer which is still * associated with an instance of Acrylic is destroyed. It means that * removeTransitData() is called even when an instance of Acrylic is * destroyed to remove all transit data installed in an AcrylicLayer instance. * If an implmentation of Acrylic may install a transit data to an instance of * AcrylicLayer, it should implement removeTransitData(). */ virtual void removeTransitData(AcrylicLayer __attribute__((__unused__)) *layer) { } bool validateAllLayers(); void sortLayers(); AcrylicLayer *getLayer(unsigned int index) { return (index < mLayers.size()) ? mLayers[index] : nullptr; } void getBackgroundColor(uint16_t *red, uint16_t *green, uint16_t *blue, uint16_t *alpha) { *red = mBackgroundColor.R; *green = mBackgroundColor.G; *blue = mBackgroundColor.B; *alpha = mBackgroundColor.A; } bool hasBackgroundColor() { return mHasBackgroundColor; } uint16_t getMaxTargetDisplayLuminance() { return mMaxTargetLuminance; } uint16_t getMinTargetDisplayLuminance() { return mMinTargetLuminance; } void *getTargetDisplayInfo() { return mTargetDisplayInfo; } private: std::vector mLayers; const HW2DCapability &mCapability; struct { uint16_t R; uint16_t G; uint16_t B; uint16_t A; } mBackgroundColor; bool mHasBackgroundColor; uint16_t mMaxTargetLuminance; uint16_t mMinTargetLuminance; void *mTargetDisplayInfo; AcrylicCanvas mCanvas; }; struct AcrylicPerformanceRequestLayer { hw2d_coord_t mSourceDimension; uint32_t mPixFormat; hw2d_rect_t mSourceRect; hw2d_rect_t mTargetRect; uint32_t mTransform; uint32_t mAttribute; }; struct AcrylicPerformanceRequestFrame { int mNumLayers; int mNumAllocLayers; int mFrameRate; uint32_t mTargetPixFormat; hw2d_coord_t mTargetDimension; bool mHasBackgroundLayer; struct AcrylicPerformanceRequestLayer *mLayers; AcrylicPerformanceRequestFrame(); ~AcrylicPerformanceRequestFrame(); bool reset(int num_layers = 0); void setSourceDimension(int layer, int width, int height, uint32_t fmt) { if (layer < mNumLayers) { mLayers[layer].mSourceDimension.hori = width; mLayers[layer].mSourceDimension.vert = height; mLayers[layer].mPixFormat = fmt; } } void setAttribute(int layer, uint32_t attribute) { if (layer < mNumLayers) mLayers[layer].mAttribute = attribute; } void setTransfer(int layer, hwc_rect_t &src_area, hwc_rect_t &out_area, uint32_t transform) { if (layer < mNumLayers) { mLayers[layer].mSourceRect.pos.hori = src_area.left; mLayers[layer].mSourceRect.pos.vert = src_area.top; mLayers[layer].mSourceRect.size.hori = src_area.right - src_area.left; mLayers[layer].mSourceRect.size.vert = src_area.bottom - src_area.top; mLayers[layer].mTargetRect.pos.hori = out_area.left; mLayers[layer].mTargetRect.pos.vert = out_area.top; mLayers[layer].mTargetRect.size.hori = out_area.right - out_area.left; mLayers[layer].mTargetRect.size.vert = out_area.bottom - out_area.top; mLayers[layer].mTransform = transform; } } void setTargetDimension(int width, int height, uint32_t fmt, bool bBackground) { mTargetDimension.hori = width; mTargetDimension.vert = height; mTargetPixFormat = fmt; mHasBackgroundLayer = bBackground; } void setFrameRate(int rate) { mFrameRate = rate; } int getLayerCount() { return mNumLayers; } }; class AcrylicPerformanceRequest { public: AcrylicPerformanceRequest(); ~AcrylicPerformanceRequest(); bool reset(int num_frames = 0); int getFrameCount() { return mNumFrames; } AcrylicPerformanceRequestFrame *getFrame(int idx) { return (idx < mNumFrames) ? &mFrames[idx] : NULL; } private: int mNumFrames; int mNumAllocFrames; AcrylicPerformanceRequestFrame *mFrames; }; #endif /*__HARDWARE_EXYNOS_ACRYLIC_H__*/