diff --git a/graphics/composer/2.1/Android.bp b/graphics/composer/2.1/Android.bp index 2bc8e93730..26c7739b85 100644 --- a/graphics/composer/2.1/Android.bp +++ b/graphics/composer/2.1/Android.bp @@ -8,11 +8,13 @@ genrule { "types.hal", "IComposer.hal", "IComposerCallback.hal", + "IComposerClient.hal", ], out: [ "android/hardware/graphics/composer/2.1/types.cpp", "android/hardware/graphics/composer/2.1/ComposerAll.cpp", "android/hardware/graphics/composer/2.1/ComposerCallbackAll.cpp", + "android/hardware/graphics/composer/2.1/ComposerClientAll.cpp", ], } @@ -24,6 +26,7 @@ genrule { "types.hal", "IComposer.hal", "IComposerCallback.hal", + "IComposerClient.hal", ], out: [ "android/hardware/graphics/composer/2.1/types.h", @@ -37,6 +40,11 @@ genrule { "android/hardware/graphics/composer/2.1/BnComposerCallback.h", "android/hardware/graphics/composer/2.1/BpComposerCallback.h", "android/hardware/graphics/composer/2.1/BsComposerCallback.h", + "android/hardware/graphics/composer/2.1/IComposerClient.h", + "android/hardware/graphics/composer/2.1/IHwComposerClient.h", + "android/hardware/graphics/composer/2.1/BnComposerClient.h", + "android/hardware/graphics/composer/2.1/BpComposerClient.h", + "android/hardware/graphics/composer/2.1/BsComposerClient.h", ], } diff --git a/graphics/composer/2.1/IComposer.hal b/graphics/composer/2.1/IComposer.hal index dd61c11b9f..771fc7d92d 100644 --- a/graphics/composer/2.1/IComposer.hal +++ b/graphics/composer/2.1/IComposer.hal @@ -16,8 +16,7 @@ package android.hardware.graphics.composer@2.1; -import android.hardware.graphics.common@1.0; -import IComposerCallback; +import IComposerClient; interface IComposer { /* @@ -47,210 +46,6 @@ interface IComposer { SKIP_CLIENT_COLOR_TRANSFORM = 2, }; - /* Display attributes queryable through getDisplayAttribute. */ - enum Attribute : int32_t { - INVALID = 0, - - /* Dimensions in pixels */ - WIDTH = 1, - HEIGHT = 2, - - /* Vsync period in nanoseconds */ - VSYNC_PERIOD = 3, - - /* - * Dots per thousand inches (DPI * 1000). Scaling by 1000 allows these - * numbers to be stored in an int32_t without losing too much - * precision. If the DPI for a configuration is unavailable or is - * considered unreliable, the device may return UNSUPPORTED instead. - */ - DPI_X = 4, - DPI_Y = 5, - }; - - /* Display requests returned by getDisplayRequests. */ - enum DisplayRequest : uint32_t { - /* - * Instructs the client to provide a new client target buffer, even if - * no layers are marked for client composition. - */ - FLIP_CLIENT_TARGET = 1 << 0, - - /* - * Instructs the client to write the result of client composition - * directly into the virtual display output buffer. If any of the - * layers are not marked as Composition::CLIENT or the given display - * is not a virtual display, this request has no effect. - */ - WRITE_CLIENT_TARGET_TO_OUTPUT = 1 << 1, - }; - - /* Layer requests returned from getDisplayRequests. */ - enum LayerRequest : uint32_t { - /* - * The client should clear its target with transparent pixels where - * this layer would be. The client may ignore this request if the - * layer must be blended. - */ - CLEAR_CLIENT_TARGET = 1 << 0, - }; - - /* Power modes for use with setPowerMode. */ - enum PowerMode : int32_t { - /* The display is fully off (blanked). */ - OFF = 0, - - /* - * These are optional low power modes. getDozeSupport may be called to - * determine whether a given display supports these modes. - */ - - /* - * The display is turned on and configured in a low power state that - * is suitable for presenting ambient information to the user, - * possibly with lower fidelity than ON, but with greater efficiency. - */ - DOZE = 1, - - /* - * The display is configured as in DOZE but may stop applying display - * updates from the client. This is effectively a hint to the device - * that drawing to the display has been suspended and that the the - * device should remain on in a low power state and continue - * displaying its current contents indefinitely until the power mode - * changes. - * - * This mode may also be used as a signal to enable hardware-based - * doze functionality. In this case, the device is free to take over - * the display and manage it autonomously to implement a low power - * always-on display. - */ - DOZE_SUSPEND = 3, - - /* The display is fully on. */ - ON = 2, - }; - - /* Vsync values passed to setVsyncEnabled. */ - enum Vsync : int32_t { - INVALID = 0, - - /* Enable vsync. */ - ENABLE = 1, - - /* Disable vsync. */ - DISABLE = 2, - }; - - /* Blend modes, settable per layer. */ - enum BlendMode : int32_t { - INVALID = 0, - - /* colorOut = colorSrc */ - NONE = 1, - - /* colorOut = colorSrc + colorDst * (1 - alphaSrc) */ - PREMULTIPLIED = 2, - - /* colorOut = colorSrc * alphaSrc + colorDst * (1 - alphaSrc) */ - COVERAGE = 3, - }; - - /* Possible composition types for a given layer. */ - enum Composition : int32_t { - INVALID = 0, - - /* - * The client will composite this layer into the client target buffer - * (provided to the device through setClientTarget). - * - * The device must not request any composition type changes for layers - * of this type. - */ - CLIENT = 1, - - /* - * The device will handle the composition of this layer through a - * hardware overlay or other similar means. - * - * Upon validateDisplay, the device may request a change from this - * type to CLIENT. - */ - DEVICE = 2, - - /* - * The device will render this layer using the color set through - * setLayerColor. If this functionality is not supported on a layer - * that the client sets to SOLID_COLOR, the device must request that - * the composition type of that layer is changed to CLIENT upon the - * next call to validateDisplay. - * - * Upon validateDisplay, the device may request a change from this - * type to CLIENT. - */ - SOLID_COLOR = 3, - - /* - * Similar to DEVICE, but the position of this layer may also be set - * asynchronously through setCursorPosition. If this functionality is - * not supported on a layer that the client sets to CURSOR, the device - * must request that the composition type of that layer is changed to - * CLIENT upon the next call to validateDisplay. - * - * Upon validateDisplay, the device may request a change from this - * type to either DEVICE or CLIENT. Changing to DEVICE will prevent - * the use of setCursorPosition but still permit the device to - * composite the layer. - */ - CURSOR = 4, - - /* - * The device will handle the composition of this layer, as well as - * its buffer updates and content synchronization. Only supported on - * devices which provide Capability::SIDEBAND_STREAM. - * - * Upon validateDisplay, the device may request a change from this - * type to either DEVICE or CLIENT, but it is unlikely that content - * will display correctly in these cases. - */ - SIDEBAND = 5, - }; - - /* Display types returned by getDisplayType. */ - enum DisplayType : int32_t { - INVALID = 0, - - /* - * All physical displays, including both internal displays and - * hotpluggable external displays. - */ - PHYSICAL = 1, - - /* Virtual displays created by createVirtualDisplay. */ - VIRTUAL = 2, - }; - - struct Rect { - int32_t left; - int32_t top; - int32_t right; - int32_t bottom; - }; - - struct FRect { - float left; - float top; - float right; - float bottom; - }; - - struct Color { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; - }; - /* * Provides a list of supported capabilities (as described in the * definition of Capability above). This list must not change after @@ -269,898 +64,14 @@ interface IComposer { dumpDebugInfo() generates (string debugInfo); /* - * Provides a IComposerCallback object for the device to call. + * Creates a client of the composer. All resources created by the client + * are owned by the client and are only visible to the client. * - * @param callback is the IComposerCallback object. - */ - registerCallback(IComposerCallback callback); - - /* - * Returns the maximum number of virtual displays supported by this device - * (which may be 0). The client will not attempt to create more than this - * many virtual displays on this device. This number must not change for - * the lifetime of the device. - */ - getMaxVirtualDisplayCount() generates (uint32_t count); - - /* - * Creates a new virtual display with the given width and height. The - * format passed into this function is the default format requested by the - * consumer of the virtual display output buffers. - * - * The display will be assumed to be on from the time the first frame is - * presented until the display is destroyed. - * - * @param width is the width in pixels. - * @param height is the height in pixels. - * @param formatHint is the default output buffer format selected by - * the consumer. - * @return error is NONE upon success. Otherwise, - * UNSUPPORTED when the width or height is too large for the - * device to be able to create a virtual display. - * NO_RESOURCES when the device is unable to create a new virtual - * display at this time. - * @return display is the newly-created virtual display. - * @return format is the format of the buffer the device will produce. - */ - createVirtualDisplay(uint32_t width, - uint32_t height, - PixelFormat formatHint) - generates (Error error, - Display display, - PixelFormat format); - - /* - * Destroys a virtual display. After this call all resources consumed by - * this display may be freed by the device and any operations performed on - * this display should fail. - * - * @param display is the virtual display to destroy. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_PARAMETER when the display handle which was passed in does - * not refer to a virtual display. - */ - destroyVirtualDisplay(Display display) generates (Error error); - - /* - * Accepts the changes required by the device from the previous - * validateDisplay call (which may be queried using - * getChangedCompositionTypes) and revalidates the display. This function - * is equivalent to requesting the changed types from - * getChangedCompositionTypes, setting those types on the corresponding - * layers, and then calling validateDisplay again. - * - * After this call it must be valid to present this display. Calling this - * after validateDisplay returns 0 changes must succeed with NONE, but - * should have no other effect. + * There can only be one client at any time. * * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * NOT_VALIDATED when validateDisplay has not been called. + * NO_RESOURCES when no more client can be created currently. + * @return client is the newly created client. */ - acceptDisplayChanges(Display display) generates (Error error); - - /* - * Creates a new layer on the given display. - * - * @param display is the display on which to create the layer. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * NO_RESOURCES when the device was unable to create a layer this - * time. - * @return layer is the handle of the new layer. - */ - createLayer(Display display) generates (Error error, Layer layer); - - /* - * Destroys the given layer. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to destroy. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - destroyLayer(Display display, Layer layer) generates (Error error); - - /* - * Retrieves which display configuration is currently active. - * - * If no display configuration is currently active, this function must - * return BAD_CONFIG. It is the responsibility of the client to call - * setActiveConfig with a valid configuration before attempting to present - * anything on the display. - * - * @param display is the display to which the active config is queried. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_CONFIG when no configuration is currently active. - * @return config is the currently active display configuration. - */ - getActiveConfig(Display display) generates (Error error, Config config); - - /* - * Retrieves the layers for which the device requires a different - * composition type than had been set prior to the last call to - * validateDisplay. The client will either update its state with these - * types and call acceptDisplayChanges, or will set new types and attempt - * to validate the display again. - * - * The number of changed layers must be the same as the value returned in - * numTypes from the last call to validateDisplay. - * - * @param display is the display to query. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * NOT_VALIDATED when validateDisplay has not been called. - * @return layers is an array of layer handles. - * @return types is an array of composition types, each corresponding to - * an element of layers. - */ - getChangedCompositionTypes(Display display) - generates (Error error, - vec layers, - vec types); - - /* - * Returns whether a client target with the given properties can be - * handled by the device. - * - * This function must return true for a client target with width and - * height equal to the active display configuration dimensions, - * PixelFormat::RGBA_8888, and Dataspace::UNKNOWN. It is not required to - * return true for any other configuration. - * - * @param display is the display to query. - * @param width is the client target width in pixels. - * @param height is the client target height in pixels. - * @param format is the client target format. - * @param dataspace is the client target dataspace, as described in - * setLayerDataspace. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * UNSUPPORTED when the given configuration is not supported. - */ - getClientTargetSupport(Display display, - uint32_t width, - uint32_t height, - PixelFormat format, - Dataspace dataspace) - generates (Error error); - - /* - * Returns the color modes supported on this display. - * - * All devices must support at least ColorMode::NATIVE. - * - * @param display is the display to query. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * @return modes is an array of color modes. - */ - getColorModes(Display display) - generates (Error error, - vec modes); - - /* - * Returns a display attribute value for a particular display - * configuration. - * - * @param display is the display to query. - * @param config is the display configuration for which to return - * attribute values. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_CONFIG when config does not name a valid configuration for - * this display. - * BAD_PARAMETER when attribute is unrecognized. - * UNSUPPORTED when attribute cannot be queried for the config. - * @return value is the value of the attribute. - */ - getDisplayAttribute(Display display, - Config config, - Attribute attribute) - generates (Error error, - int32_t value); - - /* - * Returns handles for all of the valid display configurations on this - * display. - * - * @param display is the display to query. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * @return configs is an array of configuration handles. - */ - getDisplayConfigs(Display display) - generates (Error error, - vec configs); - - /* - * Returns a human-readable version of the display's name. - * - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * @return name is the name of the display. - */ - getDisplayName(Display display) generates (Error error, string name); - - /* - * Returns the display requests and the layer requests required for the - * last validated configuration. - * - * Display requests provide information about how the client should handle - * the client target. Layer requests provide information about how the - * client should handle an individual layer. - * - * The number of layer requests must be equal to the value returned in - * numRequests from the last call to validateDisplay. - * - * @param display is the display to query. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * NOT_VALIDATED when validateDisplay has not been called. - * @return displayRequestMask is the display requests for the current - * validated state. - * @return layers is an array of layers which all have at least one - * request. - * @return layerRequestMasks is the requests corresponding to each element - * of layers. - */ - getDisplayRequests(Display display) - generates (Error error, - uint32_t displayRequestMask, - vec layers, - vec layerRequestMasks); - - /* - * Returns whether the given display is a physical or virtual display. - * - * @param display is the display to query. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * @return type is the type of the display. - */ - getDisplayType(Display display) generates (Error error, DisplayType type); - - /* - * Returns whether the given display supports PowerMode::DOZE and - * PowerMode::DOZE_SUSPEND. DOZE_SUSPEND may not provide any benefit over - * DOZE (see the definition of PowerMode for more information), but if - * both DOZE and DOZE_SUSPEND are no different from PowerMode::ON, the - * device should not claim support. - * - * @param display is the display to query. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * @return support is true only when the display supports doze modes. - */ - getDozeSupport(Display display) generates (Error error, bool support); - - /* - * Returns the high dynamic range (HDR) capabilities of the given display, - * which are invariant with regard to the active configuration. - * - * Displays which are not HDR-capable must return no types. - * - * @param display is the display to query. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * @return types is an array of HDR types, may have 0 elements if the - * display is not HDR-capable. - * @return maxLuminance is the desired content maximum luminance for this - * display in cd/m^2. - * @return maxAverageLuminance - the desired content maximum frame-average - * luminance for this display in cd/m^2. - * @return minLuminance is the desired content minimum luminance for this - * display in cd/m^2. - */ - getHdrCapabilities(Display display) - generates (Error error, - vec types, - float maxLuminance, - float maxAverageLuminance, - float minLuminance); - - /* - * Retrieves the release fences for device layers on this display which - * will receive new buffer contents this frame. - * - * A release fence is a file descriptor referring to a sync fence object - * which will be signaled after the device has finished reading from the - * buffer presented in the prior frame. This indicates that it is safe to - * start writing to the buffer again. If a given layer's fence is not - * returned from this function, it will be assumed that the buffer - * presented on the previous frame is ready to be written. - * - * The fences returned by this function should be unique for each layer - * (even if they point to the same underlying sync object). - * - * @param display is the display to query. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * @return layers is an array of layer handles. - * @return fences is handle that contains an array of sync fence file - * descriptors as described above, each corresponding to an - * element of layers. - */ - getReleaseFences(Display display) - generates (Error error, - vec layers, - handle releaseFences); - - /* - * Presents the current display contents on the screen (or in the case of - * virtual displays, into the output buffer). - * - * Prior to calling this function, the display must be successfully - * validated with validateDisplay. Note that setLayerBuffer and - * setLayerSurfaceDamage specifically do not count as layer state, so if - * there are no other changes to the layer state (or to the buffer's - * properties as described in setLayerBuffer), then it is safe to call - * this function without first validating the display. - * - * If this call succeeds, presentFence will be populated with a file - * descriptor referring to a present sync fence object. For physical - * displays, this fence will be signaled at the vsync when the result of - * composition of this frame starts to appear (for video-mode panels) or - * starts to transfer to panel memory (for command-mode panels). For - * virtual displays, this fence will be signaled when writes to the output - * buffer have completed and it is safe to read from it. - * - * @param display is the display to present. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * NO_RESOURCES when no valid output buffer has been set for a - * virtual display. - * NOT_VALIDATED when validateDisplay has not successfully been - * called for this display. - * @return presentFence is a sync fence file descriptor as described - * above. - */ - presentDisplay(Display display) - generates (Error error, - handle presentFence); - - /* - * Sets the active configuration for this display. Upon returning, the - * given display configuration should be active and remain so until either - * this function is called again or the display is disconnected. - * - * @param display is the display to which the active config is set. - * @param config is the new display configuration. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_CONFIG when the configuration handle passed in is not valid - * for this display. - */ - setActiveConfig(Display display, Config config) generates (Error error); - - /* - * Sets the buffer handle which will receive the output of client - * composition. Layers marked as Composition::CLIENT will be composited - * into this buffer prior to the call to presentDisplay, and layers not - * marked as Composition::CLIENT should be composited with this buffer by - * the device. - * - * The buffer handle provided may be empty if no layers are being - * composited by the client. This must not result in an error (unless an - * invalid display handle is also provided). - * - * Also provides a file descriptor referring to an acquire sync fence - * object, which will be signaled when it is safe to read from the client - * target buffer. If it is already safe to read from this buffer, an - * empty handle may be passed instead. - * - * For more about dataspaces, see setLayerDataspace. - * - * The damage parameter describes a surface damage region as defined in - * the description of setLayerSurfaceDamage. - * - * Will be called before presentDisplay if any of the layers are marked as - * Composition::CLIENT. If no layers are so marked, then it is not - * necessary to call this function. It is not necessary to call - * validateDisplay after changing the target through this function. - * - * @param display is the display to which the client target is set. - * @param target is the new target buffer. - * @param acquireFence is a sync fence file descriptor as described above. - * @param dataspace is the dataspace of the buffer, as described in - * setLayerDataspace. - * @param damage is the surface damage region. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_PARAMETER when the new target handle was invalid. - */ - setClientTarget(Display display, - handle target, - handle acquireFence, - Dataspace dataspace, - vec damage) - generates (Error error); - - /* - * Sets the color mode of the given display. - * - * Upon returning from this function, the color mode change must have - * fully taken effect. - * - * All devices must support at least ColorMode::NATIVE, and displays are - * assumed to be in this mode upon hotplug. - * - * @param display is the display to which the color mode is set. - * @param mode is the mode to set to. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_PARAMETER when mode is not a valid color mode. - * UNSUPPORTED when mode is not supported on this display. - */ - setColorMode(Display display, ColorMode mode) generates (Error error); - - /* - * Sets a color transform which will be applied after composition. - * - * If hint is not ColorTransform::ARBITRARY, then the device may use the - * hint to apply the desired color transform instead of using the color - * matrix directly. - * - * If the device is not capable of either using the hint or the matrix to - * apply the desired color transform, it should force all layers to client - * composition during validateDisplay. - * - * If Capability::SKIP_CLIENT_COLOR_TRANSFORM is present, then the client - * will never apply the color transform during client composition, even if - * all layers are being composed by the client. - * - * The matrix provided is an affine color transformation of the following - * form: - * - * |r.r r.g r.b 0| - * |g.r g.g g.b 0| - * |b.r b.g b.b 0| - * |Tr Tg Tb 1| - * - * This matrix will be provided in row-major form: - * - * {r.r, r.g, r.b, 0, g.r, ...}. - * - * Given a matrix of this form and an input color [R_in, G_in, B_in], the - * output color [R_out, G_out, B_out] will be: - * - * R_out = R_in * r.r + G_in * g.r + B_in * b.r + Tr - * G_out = R_in * r.g + G_in * g.g + B_in * b.g + Tg - * B_out = R_in * r.b + G_in * g.b + B_in * b.b + Tb - * - * @param display is the display to which the color transform is set. - * @param matrix is a 4x4 transform matrix (16 floats) as described above. - * @param hint is a hint value which may be used instead of the given - * matrix unless it is ColorTransform::ARBITRARY. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_PARAMETER when hint is not a valid color transform hint. - */ - setColorTransform(Display display, - vec matrix, - ColorTransform hint) - generates (Error error); - - /* - * Sets the output buffer for a virtual display. That is, the buffer to - * which the composition result will be written. - * - * Also provides a file descriptor referring to a release sync fence - * object, which will be signaled when it is safe to write to the output - * buffer. If it is already safe to write to the output buffer, an empty - * handle may be passed instead. - * - * Must be called at least once before presentDisplay, but does not have - * any interaction with layer state or display validation. - * - * @param display is the virtual display to which the output buffer is - * set. - * @param buffer is the new output buffer. - * @param releaseFence is a sync fence file descriptor as described above. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_PARAMETER when the new output buffer handle was invalid. - * UNSUPPORTED when display does not refer to a virtual display. - */ - setOutputBuffer(Display display, - handle buffer, - handle releaseFence) - generates (Error error); - - /* - * Sets the power mode of the given display. The transition must be - * complete when this function returns. It is valid to call this function - * multiple times with the same power mode. - * - * All displays must support PowerMode::ON and PowerMode::OFF. Whether a - * display supports PowerMode::DOZE or PowerMode::DOZE_SUSPEND may be - * queried using getDozeSupport. - * - * @param display is the display to which the power mode is set. - * @param mode is the new power mode. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_PARAMETER when mode was not a valid power mode. - * UNSUPPORTED when mode is not supported on this display. - */ - setPowerMode(Display display, PowerMode mode) generates (Error error); - - /* - * Enables or disables the vsync signal for the given display. Virtual - * displays never generate vsync callbacks, and any attempt to enable - * vsync for a virtual display though this function must succeed and have - * no other effect. - * - * @param display is the display to which the vsync mode is set. - * @param enabled indicates whether to enable or disable vsync - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_PARAMETER when enabled was an invalid value. - */ - setVsyncEnabled(Display display, Vsync enabled) generates (Error error); - - /* - * Instructs the device to inspect all of the layer state and determine if - * there are any composition type changes necessary before presenting the - * display. Permitted changes are described in the definition of - * Composition above. - * - * Also returns the number of layer requests required by the given layer - * configuration. - * - * @param display is the display to validate. - * @return error is NONE or HAS_CHANGES upon success. - * NONE when no changes are necessary and it is safe to present - * the display using the current layer state. - * HAS_CHANGES when composition type changes are needed. - * Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * @return numTypes is the number of composition type changes required by - * the device; if greater than 0, the client must either set and - * validate new types, or call acceptDisplayChanges to accept the - * changes returned by getChangedCompositionTypes. It must be the - * same as the number of changes returned by - * getChangedCompositionTypes (see the declaration of that - * function for more information). - * @return numRequests is the number of layer requests required by this - * layer configuration. It must be equal to the number of layer - * requests returned by getDisplayRequests (see the declaration of - * that function for more information). - */ - validateDisplay(Display display) - generates (Error error, - uint32_t numTypes, - uint32_t numRequests); - - /* - * Layer Functions - * - * These are functions which operate on layers, but which do not modify - * state that must be validated before use. See also 'Layer State - * Functions' below. - */ - - /* - * Asynchronously sets the position of a cursor layer. - * - * Prior to validateDisplay, a layer may be marked as Composition::CURSOR. - * If validation succeeds (i.e., the device does not request a composition - * change for that layer), then once a buffer has been set for the layer - * and it has been presented, its position may be set by this function at - * any time between presentDisplay and any subsequent validateDisplay - * calls for this display. - * - * Once validateDisplay is called, this function will not be called again - * until the validate/present sequence is completed. - * - * May be called from any thread so long as it is not interleaved with the - * validate/present sequence as described above. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the position is set. - * @param x is the new x coordinate (in pixels from the left of the - * screen). - * @param y is the new y coordinate (in pixels from the top of the - * screen). - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when the layer is invalid or is not currently marked - * as Composition::CURSOR. - * NOT_VALIDATED when the device is currently in the middle of the - * validate/present sequence. - */ - setCursorPosition(Display display, - Layer layer, - int32_t x, - int32_t y) - generates (Error error); - - /* - * Sets the buffer handle to be displayed for this layer. If the buffer - * properties set at allocation time (width, height, format, and usage) - * have not changed since the previous frame, it is not necessary to call - * validateDisplay before calling presentDisplay unless new state needs to - * be validated in the interim. - * - * Also provides a file descriptor referring to an acquire sync fence - * object, which will be signaled when it is safe to read from the given - * buffer. If it is already safe to read from the buffer, an empty handle - * may be passed instead. - * - * This function must return NONE and have no other effect if called for a - * layer with a composition type of Composition::SOLID_COLOR (because it - * has no buffer) or Composition::SIDEBAND or Composition::CLIENT (because - * synchronization and buffer updates for these layers are handled - * elsewhere). - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the buffer is set. - * @param buffer is the buffer handle to set. - * @param acquireFence is a sync fence file descriptor as described above. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - * BAD_PARAMETER when the buffer handle passed in was invalid. - */ - setLayerBuffer(Display display, - Layer layer, - handle buffer, - handle acquireFence) - generates (Error error); - - /* - * Provides the region of the source buffer which has been modified since - * the last frame. This region does not need to be validated before - * calling presentDisplay. - * - * Once set through this function, the damage region remains the same - * until a subsequent call to this function. - * - * If damage is non-empty, then it may be assumed that any portion of the - * source buffer not covered by one of the rects has not been modified - * this frame. If damage is empty, then the whole source buffer must be - * treated as if it has been modified. - * - * If the layer's contents are not modified relative to the prior frame, - * damage will contain exactly one empty rect([0, 0, 0, 0]). - * - * The damage rects are relative to the pre-transformed buffer, and their - * origin is the top-left corner. They will not exceed the dimensions of - * the latched buffer. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the damage region is set. - * @param damage is the new surface damage region. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - setLayerSurfaceDamage(Display display, - Layer layer, - vec damage) - generates (Error error); - - /* - * Layer State Functions - * - * These functions modify the state of a given layer. They do not take - * effect until the display configuration is successfully validated with - * validateDisplay and the display contents are presented with - * presentDisplay. - */ - - /* - * Sets the blend mode of the given layer. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the blend mode is set. - * @param mode is the new blend mode. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - * BAD_PARAMETER when an invalid blend mode was passed in. - */ - setLayerBlendMode(Display display, - Layer layer, - BlendMode mode) - generates (Error error); - - /* - * Sets the color of the given layer. If the composition type of the layer - * is not Composition::SOLID_COLOR, this call must succeed and have no - * other effect. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the blend mode is set. - * @param color is the new color. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - setLayerColor(Display display, - Layer layer, - Color color) - generates (Error error); - - /* - * Sets the desired composition type of the given layer. During - * validateDisplay, the device may request changes to the composition - * types of any of the layers as described in the definition of - * Composition above. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the blend mode is set. - * @param type is the new composition type. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - * BAD_PARAMETER when an invalid composition type was passed in. - * UNSUPPORTED when a valid composition type was passed in, but it - * is not supported by this device. - */ - setLayerCompositionType(Display display, - Layer layer, - Composition type) - generates (Error error); - - /* - * Sets the dataspace that the current buffer on this layer is in. - * - * The dataspace provides more information about how to interpret the - * buffer contents, such as the encoding standard and color transform. - * - * See the values of Dataspace for more information. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the dataspace is set. - * @param dataspace is the new dataspace. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - setLayerDataspace(Display display, - Layer layer, - Dataspace dataspace) - generates (Error error); - - /* - * Sets the display frame (the portion of the display covered by a layer) - * of the given layer. This frame will not exceed the display dimensions. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the frame is set. - * @param frame is the new display frame. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - setLayerDisplayFrame(Display display, - Layer layer, - Rect frame) - generates (Error error); - - /* - * Sets an alpha value (a floating point value in the range [0.0, 1.0]) - * which will be applied to the whole layer. It can be conceptualized as a - * preprocessing step which applies the following function: - * if (blendMode == BlendMode::PREMULTIPLIED) - * out.rgb = in.rgb * planeAlpha - * out.a = in.a * planeAlpha - * - * If the device does not support this operation on a layer which is - * marked Composition::DEVICE, it must request a composition type change - * to Composition::CLIENT upon the next validateDisplay call. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the plane alpha is set. - * @param alpha is the plane alpha value to apply. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - setLayerPlaneAlpha(Display display, - Layer layer, - float alpha) - generates (Error error); - - /* - * Sets the sideband stream for this layer. If the composition type of the - * given layer is not Composition::SIDEBAND, this call must succeed and - * have no other effect. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the sideband stream is set. - * @param stream is the new sideband stream. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - * BAD_PARAMETER when an invalid sideband stream was passed in. - */ - setLayerSidebandStream(Display display, - Layer layer, - handle stream) - generates (Error error); - - /* - * Sets the source crop (the portion of the source buffer which will fill - * the display frame) of the given layer. This crop rectangle will not - * exceed the dimensions of the latched buffer. - * - * If the device is not capable of supporting a true float source crop - * (i.e., it will truncate or round the floats to integers), it should set - * this layer to Composition::CLIENT when crop is non-integral for the - * most accurate rendering. - * - * If the device cannot support float source crops, but still wants to - * handle the layer, it should use the following code (or similar) to - * convert to an integer crop: - * intCrop.left = (int) ceilf(crop.left); - * intCrop.top = (int) ceilf(crop.top); - * intCrop.right = (int) floorf(crop.right); - * intCrop.bottom = (int) floorf(crop.bottom); - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the source crop is set. - * @param crop is the new source crop. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - setLayerSourceCrop(Display display, - Layer layer, - FRect crop) - generates (Error error); - - /* - * Sets the transform (rotation/flip) of the given layer. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the transform is set. - * @param transform is the new transform. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - * BAD_PARAMETER when an invalid transform was passed in. - */ - setLayerTransform(Display display, - Layer layer, - Transform transform) - generates (Error error); - - /* - * Specifies the portion of the layer that is visible, including portions - * under translucent areas of other layers. The region is in screen space, - * and will not exceed the dimensions of the screen. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the visible region is set. - * @param visible is the new visible region, in screen space. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - setLayerVisibleRegion(Display display, - Layer layer, - vec visible) - generates (Error error); - - /* - * Sets the desired Z order (height) of the given layer. A layer with a - * greater Z value occludes a layer with a lesser Z value. - * - * @param display is the display on which the layer was created. - * @param layer is the layer to which the Z order is set. - * @param z is the new Z order. - * @return error is NONE upon success. Otherwise, - * BAD_DISPLAY when an invalid display handle was passed in. - * BAD_LAYER when an invalid layer handle was passed in. - */ - setLayerZOrder(Display display, - Layer layer, - uint32_t z) - generates (Error error); + createClient() generates (Error error, IComposerClient client); }; diff --git a/graphics/composer/2.1/IComposerClient.hal b/graphics/composer/2.1/IComposerClient.hal new file mode 100644 index 0000000000..1a82215af6 --- /dev/null +++ b/graphics/composer/2.1/IComposerClient.hal @@ -0,0 +1,1118 @@ +/* + * 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. + */ + +package android.hardware.graphics.composer@2.1; + +import android.hardware.graphics.common@1.0; +import IComposerCallback; + +interface IComposerClient { + /* Display attributes queryable through getDisplayAttribute. */ + enum Attribute : int32_t { + INVALID = 0, + + /* Dimensions in pixels */ + WIDTH = 1, + HEIGHT = 2, + + /* Vsync period in nanoseconds */ + VSYNC_PERIOD = 3, + + /* + * Dots per thousand inches (DPI * 1000). Scaling by 1000 allows these + * numbers to be stored in an int32_t without losing too much + * precision. If the DPI for a configuration is unavailable or is + * considered unreliable, the device may return UNSUPPORTED instead. + */ + DPI_X = 4, + DPI_Y = 5, + }; + + /* Display requests returned by getDisplayRequests. */ + enum DisplayRequest : uint32_t { + /* + * Instructs the client to provide a new client target buffer, even if + * no layers are marked for client composition. + */ + FLIP_CLIENT_TARGET = 1 << 0, + + /* + * Instructs the client to write the result of client composition + * directly into the virtual display output buffer. If any of the + * layers are not marked as Composition::CLIENT or the given display + * is not a virtual display, this request has no effect. + */ + WRITE_CLIENT_TARGET_TO_OUTPUT = 1 << 1, + }; + + /* Layer requests returned from getDisplayRequests. */ + enum LayerRequest : uint32_t { + /* + * The client must clear its target with transparent pixels where + * this layer would be. The client may ignore this request if the + * layer must be blended. + */ + CLEAR_CLIENT_TARGET = 1 << 0, + }; + + /* Power modes for use with setPowerMode. */ + enum PowerMode : int32_t { + /* The display is fully off (blanked). */ + OFF = 0, + + /* + * These are optional low power modes. getDozeSupport may be called to + * determine whether a given display supports these modes. + */ + + /* + * The display is turned on and configured in a low power state that + * is suitable for presenting ambient information to the user, + * possibly with lower fidelity than ON, but with greater efficiency. + */ + DOZE = 1, + + /* + * The display is configured as in DOZE but may stop applying display + * updates from the client. This is effectively a hint to the device + * that drawing to the display has been suspended and that the the + * device must remain on in a low power state and continue + * displaying its current contents indefinitely until the power mode + * changes. + * + * This mode may also be used as a signal to enable hardware-based + * doze functionality. In this case, the device is free to take over + * the display and manage it autonomously to implement a low power + * always-on display. + */ + DOZE_SUSPEND = 3, + + /* The display is fully on. */ + ON = 2, + }; + + /* Vsync values passed to setVsyncEnabled. */ + enum Vsync : int32_t { + INVALID = 0, + + /* Enable vsync. */ + ENABLE = 1, + + /* Disable vsync. */ + DISABLE = 2, + }; + + /* Blend modes, settable per layer. */ + enum BlendMode : int32_t { + INVALID = 0, + + /* colorOut = colorSrc */ + NONE = 1, + + /* colorOut = colorSrc + colorDst * (1 - alphaSrc) */ + PREMULTIPLIED = 2, + + /* colorOut = colorSrc * alphaSrc + colorDst * (1 - alphaSrc) */ + COVERAGE = 3, + }; + + /* Possible composition types for a given layer. */ + enum Composition : int32_t { + INVALID = 0, + + /* + * The client must composite this layer into the client target buffer + * (provided to the device through setClientTarget). + * + * The device must not request any composition type changes for layers + * of this type. + */ + CLIENT = 1, + + /* + * The device must handle the composition of this layer through a + * hardware overlay or other similar means. + * + * Upon validateDisplay, the device may request a change from this + * type to CLIENT. + */ + DEVICE = 2, + + /* + * The device must render this layer using the color set through + * setLayerColor. If this functionality is not supported on a layer + * that the client sets to SOLID_COLOR, the device must request that + * the composition type of that layer is changed to CLIENT upon the + * next call to validateDisplay. + * + * Upon validateDisplay, the device may request a change from this + * type to CLIENT. + */ + SOLID_COLOR = 3, + + /* + * Similar to DEVICE, but the position of this layer may also be set + * asynchronously through setCursorPosition. If this functionality is + * not supported on a layer that the client sets to CURSOR, the device + * must request that the composition type of that layer is changed to + * CLIENT upon the next call to validateDisplay. + * + * Upon validateDisplay, the device may request a change from this + * type to either DEVICE or CLIENT. Changing to DEVICE will prevent + * the use of setCursorPosition but still permit the device to + * composite the layer. + */ + CURSOR = 4, + + /* + * The device must handle the composition of this layer, as well as + * its buffer updates and content synchronization. Only supported on + * devices which provide Capability::SIDEBAND_STREAM. + * + * Upon validateDisplay, the device may request a change from this + * type to either DEVICE or CLIENT, but it is unlikely that content + * will display correctly in these cases. + */ + SIDEBAND = 5, + }; + + /* Display types returned by getDisplayType. */ + enum DisplayType : int32_t { + INVALID = 0, + + /* + * All physical displays, including both internal displays and + * hotpluggable external displays. + */ + PHYSICAL = 1, + + /* Virtual displays created by createVirtualDisplay. */ + VIRTUAL = 2, + }; + + /* Special index values (always negative) for command queue commands. */ + enum HandleIndex : int32_t { + /* No handle */ + EMPTY = -1, + + /* Use cached handle */ + CACHED = -2, + }; + + struct Rect { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + }; + + struct FRect { + float left; + float top; + float right; + float bottom; + }; + + struct Color { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + }; + + /* + * Provides a IComposerCallback object for the device to call. + * + * This function must be called only once. + * + * @param callback is the IComposerCallback object. + */ + registerCallback(IComposerCallback callback); + + /* + * Returns the maximum number of virtual displays supported by this device + * (which may be 0). The client must not attempt to create more than this + * many virtual displays on this device. This number must not change for + * the lifetime of the device. + * + * @return count is the maximum number of virtual displays supported. + */ + getMaxVirtualDisplayCount() generates (uint32_t count); + + /* + * Creates a new virtual display with the given width and height. The + * format passed into this function is the default format requested by the + * consumer of the virtual display output buffers. + * + * The display must be assumed to be on from the time the first frame is + * presented until the display is destroyed. + * + * @param width is the width in pixels. + * @param height is the height in pixels. + * @param formatHint is the default output buffer format selected by + * the consumer. + * @param outputBufferSlotCount is the number of output buffer slots to be + * reserved. + * @return error is NONE upon success. Otherwise, + * UNSUPPORTED when the width or height is too large for the + * device to be able to create a virtual display. + * NO_RESOURCES when the device is unable to create a new virtual + * display at this time. + * @return display is the newly-created virtual display. + * @return format is the format of the buffer the device will produce. + */ + createVirtualDisplay(uint32_t width, + uint32_t height, + PixelFormat formatHint, + uint32_t outputBufferSlotCount) + generates (Error error, + Display display, + PixelFormat format); + + /* + * Destroys a virtual display. After this call all resources consumed by + * this display may be freed by the device and any operations performed on + * this display must fail. + * + * @param display is the virtual display to destroy. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_PARAMETER when the display handle which was passed in does + * not refer to a virtual display. + */ + destroyVirtualDisplay(Display display) generates (Error error); + + /* + * Creates a new layer on the given display. + * + * @param display is the display on which to create the layer. + * @param bufferSlotCount is the number of buffer slot to be reserved. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * NO_RESOURCES when the device was unable to create a layer this + * time. + * @return layer is the handle of the new layer. + */ + createLayer(Display display, + uint32_t bufferSlotCount) + generates (Error error, + Layer layer); + + /* + * Destroys the given layer. + * + * @param display is the display on which the layer was created. + * @param layer is the layer to destroy. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_LAYER when an invalid layer handle was passed in. + */ + destroyLayer(Display display, Layer layer) generates (Error error); + + /* + * Retrieves which display configuration is currently active. + * + * If no display configuration is currently active, this function must + * return BAD_CONFIG. It is the responsibility of the client to call + * setActiveConfig with a valid configuration before attempting to present + * anything on the display. + * + * @param display is the display to which the active config is queried. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_CONFIG when no configuration is currently active. + * @return config is the currently active display configuration. + */ + getActiveConfig(Display display) generates (Error error, Config config); + + /* + * Returns whether a client target with the given properties can be + * handled by the device. + * + * This function must return true for a client target with width and + * height equal to the active display configuration dimensions, + * PixelFormat::RGBA_8888, and Dataspace::UNKNOWN. It is not required to + * return true for any other configuration. + * + * @param display is the display to query. + * @param width is the client target width in pixels. + * @param height is the client target height in pixels. + * @param format is the client target format. + * @param dataspace is the client target dataspace, as described in + * setLayerDataspace. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * UNSUPPORTED when the given configuration is not supported. + */ + getClientTargetSupport(Display display, + uint32_t width, + uint32_t height, + PixelFormat format, + Dataspace dataspace) + generates (Error error); + + /* + * Returns the color modes supported on this display. + * + * All devices must support at least ColorMode::NATIVE. + * + * @param display is the display to query. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * @return modes is an array of color modes. + */ + getColorModes(Display display) + generates (Error error, + vec modes); + + /* + * Returns a display attribute value for a particular display + * configuration. + * + * @param display is the display to query. + * @param config is the display configuration for which to return + * attribute values. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_CONFIG when config does not name a valid configuration for + * this display. + * BAD_PARAMETER when attribute is unrecognized. + * UNSUPPORTED when attribute cannot be queried for the config. + * @return value is the value of the attribute. + */ + getDisplayAttribute(Display display, + Config config, + Attribute attribute) + generates (Error error, + int32_t value); + + /* + * Returns handles for all of the valid display configurations on this + * display. + * + * @param display is the display to query. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * @return configs is an array of configuration handles. + */ + getDisplayConfigs(Display display) + generates (Error error, + vec configs); + + /* + * Returns a human-readable version of the display's name. + * + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * @return name is the name of the display. + */ + getDisplayName(Display display) generates (Error error, string name); + + /* + * Returns whether the given display is a physical or virtual display. + * + * @param display is the display to query. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * @return type is the type of the display. + */ + getDisplayType(Display display) generates (Error error, DisplayType type); + + /* + * Returns whether the given display supports PowerMode::DOZE and + * PowerMode::DOZE_SUSPEND. DOZE_SUSPEND may not provide any benefit over + * DOZE (see the definition of PowerMode for more information), but if + * both DOZE and DOZE_SUSPEND are no different from PowerMode::ON, the + * device must not claim support. + * + * @param display is the display to query. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * @return support is true only when the display supports doze modes. + */ + getDozeSupport(Display display) generates (Error error, bool support); + + /* + * Returns the high dynamic range (HDR) capabilities of the given display, + * which are invariant with regard to the active configuration. + * + * Displays which are not HDR-capable must return no types. + * + * @param display is the display to query. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * @return types is an array of HDR types, may have 0 elements if the + * display is not HDR-capable. + * @return maxLuminance is the desired content maximum luminance for this + * display in cd/m^2. + * @return maxAverageLuminance - the desired content maximum frame-average + * luminance for this display in cd/m^2. + * @return minLuminance is the desired content minimum luminance for this + * display in cd/m^2. + */ + getHdrCapabilities(Display display) + generates (Error error, + vec types, + float maxLuminance, + float maxAverageLuminance, + float minLuminance); + + /* + * Set the number of client target slots to be reserved. + * + * @param display is the display to which the slots are reserved. + * @param clientTargetSlotCount is the slot count for client targets. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * NO_RESOURCES when unable to reserve the slots. + */ + setClientTargetSlotCount(Display display, + uint32_t clientTargetSlotCount) + generates (Error error); + + /* + * Sets the active configuration for this display. Upon returning, the + * given display configuration must be active and remain so until either + * this function is called again or the display is disconnected. + * + * @param display is the display to which the active config is set. + * @param config is the new display configuration. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_CONFIG when the configuration handle passed in is not valid + * for this display. + */ + setActiveConfig(Display display, Config config) generates (Error error); + + /* + * Sets the color mode of the given display. + * + * Upon returning from this function, the color mode change must have + * fully taken effect. + * + * All devices must support at least ColorMode::NATIVE, and displays are + * assumed to be in this mode upon hotplug. + * + * @param display is the display to which the color mode is set. + * @param mode is the mode to set to. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_PARAMETER when mode is not a valid color mode. + * UNSUPPORTED when mode is not supported on this display. + */ + setColorMode(Display display, ColorMode mode) generates (Error error); + + /* + * Sets the power mode of the given display. The transition must be + * complete when this function returns. It is valid to call this function + * multiple times with the same power mode. + * + * All displays must support PowerMode::ON and PowerMode::OFF. Whether a + * display supports PowerMode::DOZE or PowerMode::DOZE_SUSPEND may be + * queried using getDozeSupport. + * + * @param display is the display to which the power mode is set. + * @param mode is the new power mode. + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_PARAMETER when mode was not a valid power mode. + * UNSUPPORTED when mode is not supported on this display. + */ + setPowerMode(Display display, PowerMode mode) generates (Error error); + + /* + * Enables or disables the vsync signal for the given display. Virtual + * displays never generate vsync callbacks, and any attempt to enable + * vsync for a virtual display though this function must succeed and have + * no other effect. + * + * @param display is the display to which the vsync mode is set. + * @param enabled indicates whether to enable or disable vsync + * @return error is NONE upon success. Otherwise, + * BAD_DISPLAY when an invalid display handle was passed in. + * BAD_PARAMETER when enabled was an invalid value. + */ + setVsyncEnabled(Display display, Vsync enabled) generates (Error error); + + /* + * Sets the input command message queue. + * + * @param descriptor is the descriptor of the input command message queue. + * @return error is NONE upon success. Otherwise, + * NO_RESOURCES when failed to set the queue temporarily. + */ + setInputCommandQueue(MQDescriptorSync descriptor) + generates (Error error); + + /* + * Gets the output command message queue. + * + * This function must only be called inside executeCommands closure. + * + * @return error is NONE upon success. Otherwise, + * NO_RESOURCES when failed to get the queue temporarily. + * @return descriptor is the descriptor of the output command queue. + */ + getOutputCommandQueue() + generates (Error error, + MQDescriptorSync descriptor); + + /* + * Executes commands from the input command message queue. Return values + * generated by the input commands are written to the output command + * message queue in the form of value commands. + * + * @param inLength is the length of input commands. + * @param inHandles is an array of handles referenced by the input + * commands. + * @return error is NONE upon success. Otherwise, + * BAD_PARAMETER when inLength is not equal to the length of + * commands in the input command message queue. + * NO_RESOURCES when the output command message queue was not + * properly drained. + * @param outQueueChanged indicates whether the output command message + * queue has changed. + * @param outLength is the length of output commands. + * @param outHandles is an array of handles referenced by the output + * commands. + */ + executeCommands(uint32_t inLength, + vec inHandles) + generates (Error error, + bool outQueueChanged, + uint32_t outLength, + vec outHandles); + + /* + * SELECT_DISPLAY has this pseudo prototype + * + * selectDisplay(Display display); + * + * Selects the current display implied by all other commands. + * + * @param display is the newly selected display. + * + * + * SELECT_LAYER has this pseudo prototype + * + * selectLayer(Layer layer); + * + * Selects the current layer implied by all implicit layer commands. + * + * @param layer is the newly selected layer. + * + * + * SET_ERROR has this pseudo prototype + * + * setError(uint32_t location, Error error); + * + * Indicates an error generated by a command. + * + * @param location is the offset of the command in the input command + * message queue. + * @param error is the error generated by the command. + * + * + * SET_CHANGED_COMPOSITION_TYPES has this pseudo prototype + * + * setChangedCompositionTypes(vec layers, + * vec types); + * + * Sets the layers for which the device requires a different composition + * type than had been set prior to the last call to VALIDATE_DISPLAY. The + * client must either update its state with these types and call + * ACCEPT_DISPLAY_CHANGES, or must set new types and attempt to validate + * the display again. + * + * @param layers is an array of layer handles. + * @param types is an array of composition types, each corresponding to + * an element of layers. + * + * + * SET_DISPLAY_REQUESTS has this pseudo prototype + * + * setDisplayRequests(uint32_t displayRequestMask, + * vec layers, + * vec layerRequestMasks); + * + * Sets the display requests and the layer requests required for the last + * validated configuration. + * + * Display requests provide information about how the client must handle + * the client target. Layer requests provide information about how the + * client must handle an individual layer. + * + * @param displayRequestMask is the display requests for the current + * validated state. + * @param layers is an array of layers which all have at least one + * request. + * @param layerRequestMasks is the requests corresponding to each element + * of layers. + * + * + * SET_PRESENT_FENCE has this pseudo prototype + * + * setPresentFence(int32_t presentFenceIndex); + * + * Sets the present fence as a result of PRESENT_DISPLAY. For physical + * displays, this fence must be signaled at the vsync when the result + * of composition of this frame starts to appear (for video-mode panels) + * or starts to transfer to panel memory (for command-mode panels). For + * virtual displays, this fence must be signaled when writes to the output + * buffer have completed and it is safe to read from it. + * + * @param presentFenceIndex is an index into outHandles array. + * + * + * SET_RELEASE_FENCES has this pseudo prototype + * + * setReleaseFences(vec layers, + * vec releaseFenceIndices); + * + * Sets the release fences for device layers on this display which will + * receive new buffer contents this frame. + * + * A release fence is a file descriptor referring to a sync fence object + * which must be signaled after the device has finished reading from the + * buffer presented in the prior frame. This indicates that it is safe to + * start writing to the buffer again. If a given layer's fence is not + * returned from this function, it must be assumed that the buffer + * presented on the previous frame is ready to be written. + * + * The fences returned by this function must be unique for each layer + * (even if they point to the same underlying sync object). + * + * @param layers is an array of layer handles. + * @param releaseFenceIndices are indices into outHandles array, each + * corresponding to an element of layers. + * + * + * SET_COLOR_TRANSFORM has this pseudo prototype + * + * setColorTransform(float[16] matrix, + * ColorTransform hint); + * + * Sets a color transform which will be applied after composition. + * + * If hint is not ColorTransform::ARBITRARY, then the device may use the + * hint to apply the desired color transform instead of using the color + * matrix directly. + * + * If the device is not capable of either using the hint or the matrix to + * apply the desired color transform, it must force all layers to client + * composition during VALIDATE_DISPLAY. + * + * If IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM is present, then + * the client must never apply the color transform during client + * composition, even if all layers are being composed by the client. + * + * The matrix provided is an affine color transformation of the following + * form: + * + * |r.r r.g r.b 0| + * |g.r g.g g.b 0| + * |b.r b.g b.b 0| + * |Tr Tg Tb 1| + * + * This matrix must be provided in row-major form: + * + * {r.r, r.g, r.b, 0, g.r, ...}. + * + * Given a matrix of this form and an input color [R_in, G_in, B_in], the + * output color [R_out, G_out, B_out] will be: + * + * R_out = R_in * r.r + G_in * g.r + B_in * b.r + Tr + * G_out = R_in * r.g + G_in * g.g + B_in * b.g + Tg + * B_out = R_in * r.b + G_in * g.b + B_in * b.b + Tb + * + * @param matrix is a 4x4 transform matrix (16 floats) as described above. + * @param hint is a hint value which may be used instead of the given + * matrix unless it is ColorTransform::ARBITRARY. + * + * + * SET_CLIENT_TARGET has this pseudo prototype + * + * setClientTarget(uint32_t targetSlot, + * int32_t targetIndex, + * int32_t acquireFenceIndex, + * Dataspace dataspace, + * vec damage); + * + * Sets the buffer handle which will receive the output of client + * composition. Layers marked as Composition::CLIENT must be composited + * into this buffer prior to the call to PRESENT_DISPLAY, and layers not + * marked as Composition::CLIENT must be composited with this buffer by + * the device. + * + * The buffer handle provided may be empty if no layers are being + * composited by the client. This must not result in an error (unless an + * invalid display handle is also provided). + * + * Also provides a file descriptor referring to an acquire sync fence + * object, which must be signaled when it is safe to read from the client + * target buffer. If it is already safe to read from this buffer, an + * empty handle may be passed instead. + * + * For more about dataspaces, see SET_LAYER_DATASPACE. + * + * The damage parameter describes a surface damage region as defined in + * the description of SET_LAYER_SURFACE_DAMAGE. + * + * Will be called before PRESENT_DISPLAY if any of the layers are marked + * as Composition::CLIENT. If no layers are so marked, then it is not + * necessary to call this function. It is not necessary to call + * validateDisplay after changing the target through this function. + * + * @param targetSlot is the client target buffer slot to use. + * @param targetIndex is an index into inHandles for the new target + * buffer. + * @param acquireFenceIndex is an index into inHandles for a sync fence + * file descriptor as described above. + * @param dataspace is the dataspace of the buffer, as described in + * setLayerDataspace. + * @param damage is the surface damage region. + * + * + * SET_OUTPUT_BUFFER has this pseudo prototype + * + * setOutputBuffer(uint32_t bufferSlot, + * int32_t bufferIndex, + * int32_t releaseFenceIndex); + * + * Sets the output buffer for a virtual display. That is, the buffer to + * which the composition result will be written. + * + * Also provides a file descriptor referring to a release sync fence + * object, which must be signaled when it is safe to write to the output + * buffer. If it is already safe to write to the output buffer, an empty + * handle may be passed instead. + * + * Must be called at least once before PRESENT_DISPLAY, but does not have + * any interaction with layer state or display validation. + * + * @param bufferSlot is the new output buffer. + * @param bufferIndex is the new output buffer. + * @param releaseFenceIndex is a sync fence file descriptor as described + * above. + * + * + * VALIDATE_DISPLAY has this pseudo prototype + * + * validateDisplay(); + * + * Instructs the device to inspect all of the layer state and determine if + * there are any composition type changes necessary before presenting the + * display. Permitted changes are described in the definition of + * Composition above. + * + * + * ACCEPT_DISPLAY_CHANGES has this pseudo prototype + * + * acceptDisplayChanges(); + * + * Accepts the changes required by the device from the previous + * validateDisplay call (which may be queried using + * getChangedCompositionTypes) and revalidates the display. This function + * is equivalent to requesting the changed types from + * getChangedCompositionTypes, setting those types on the corresponding + * layers, and then calling validateDisplay again. + * + * After this call it must be valid to present this display. Calling this + * after validateDisplay returns 0 changes must succeed with NONE, but + * must have no other effect. + * + * + * PRESENT_DISPLAY has this pseudo prototype + * + * presentDisplay(); + * + * Presents the current display contents on the screen (or in the case of + * virtual displays, into the output buffer). + * + * Prior to calling this function, the display must be successfully + * validated with validateDisplay. Note that setLayerBuffer and + * setLayerSurfaceDamage specifically do not count as layer state, so if + * there are no other changes to the layer state (or to the buffer's + * properties as described in setLayerBuffer), then it is safe to call + * this function without first validating the display. + * + * + * SET_LAYER_CURSOR_POSITION has this pseudo prototype + * + * setLayerCursorPosition(int32_t x, int32_t y); + * + * Asynchronously sets the position of a cursor layer. + * + * Prior to validateDisplay, a layer may be marked as Composition::CURSOR. + * If validation succeeds (i.e., the device does not request a composition + * change for that layer), then once a buffer has been set for the layer + * and it has been presented, its position may be set by this function at + * any time between presentDisplay and any subsequent validateDisplay + * calls for this display. + * + * Once validateDisplay is called, this function must not be called again + * until the validate/present sequence is completed. + * + * May be called from any thread so long as it is not interleaved with the + * validate/present sequence as described above. + * + * @param layer is the layer to which the position is set. + * @param x is the new x coordinate (in pixels from the left of the + * screen). + * @param y is the new y coordinate (in pixels from the top of the + * screen). + * + * + * SET_LAYER_BUFFER has this pseudo prototype + * + * setLayerBuffer(uint32_t bufferSlot, + * int32_t bufferIndex, + * int32_t acquireFenceIndex); + * + * Sets the buffer handle to be displayed for this layer. If the buffer + * properties set at allocation time (width, height, format, and usage) + * have not changed since the previous frame, it is not necessary to call + * validateDisplay before calling presentDisplay unless new state needs to + * be validated in the interim. + * + * Also provides a file descriptor referring to an acquire sync fence + * object, which must be signaled when it is safe to read from the given + * buffer. If it is already safe to read from the buffer, an empty handle + * may be passed instead. + * + * This function must return NONE and have no other effect if called for a + * layer with a composition type of Composition::SOLID_COLOR (because it + * has no buffer) or Composition::SIDEBAND or Composition::CLIENT (because + * synchronization and buffer updates for these layers are handled + * elsewhere). + * + * @param layer is the layer to which the buffer is set. + * @param bufferSlot is the buffer slot to use. + * @param bufferIndex is the buffer handle to set. + * @param acquireFenceIndex is a sync fence file descriptor as described above. + * + * + * SET_LAYER_SURFACE_DAMAGE has this pseudo prototype + * + * setLayerSurfaceDamage(vec damage); + * + * Provides the region of the source buffer which has been modified since + * the last frame. This region does not need to be validated before + * calling presentDisplay. + * + * Once set through this function, the damage region remains the same + * until a subsequent call to this function. + * + * If damage is non-empty, then it may be assumed that any portion of the + * source buffer not covered by one of the rects has not been modified + * this frame. If damage is empty, then the whole source buffer must be + * treated as if it has been modified. + * + * If the layer's contents are not modified relative to the prior frame, + * damage must contain exactly one empty rect([0, 0, 0, 0]). + * + * The damage rects are relative to the pre-transformed buffer, and their + * origin is the top-left corner. They must not exceed the dimensions of + * the latched buffer. + * + * @param layer is the layer to which the damage region is set. + * @param damage is the new surface damage region. + * + * + * SET_LAYER_BLEND_MODE has this pseudo prototype + * + * setLayerBlendMode(BlendMode mode) + * + * Sets the blend mode of the given layer. + * + * @param mode is the new blend mode. + * + * + * SET_LAYER_COLOR has this pseudo prototype + * + * setLayerColor(Color color); + * + * Sets the color of the given layer. If the composition type of the layer + * is not Composition::SOLID_COLOR, this call must succeed and have no + * other effect. + * + * @param color is the new color. + * + * + * SET_LAYER_COMPOSITION_TYPE has this pseudo prototype + * + * setLayerCompositionType(Composition type); + * + * Sets the desired composition type of the given layer. During + * validateDisplay, the device may request changes to the composition + * types of any of the layers as described in the definition of + * Composition above. + * + * @param type is the new composition type. + * + * + * SET_LAYER_DATASPACE has this pseudo prototype + * + * setLayerDataspace(Dataspace dataspace); + * + * Sets the dataspace that the current buffer on this layer is in. + * + * The dataspace provides more information about how to interpret the + * buffer contents, such as the encoding standard and color transform. + * + * See the values of Dataspace for more information. + * + * @param dataspace is the new dataspace. + * + * + * SET_LAYER_DISPLAY_FRAME has this pseudo prototype + * + * setLayerDisplayFrame(Rect frame); + * + * Sets the display frame (the portion of the display covered by a layer) + * of the given layer. This frame must not exceed the display dimensions. + * + * @param frame is the new display frame. + * + * + * SET_LAYER_PLANE_ALPHA has this pseudo prototype + * + * setLayerPlaneAlpha(float alpha); + * + * Sets an alpha value (a floating point value in the range [0.0, 1.0]) + * which will be applied to the whole layer. It can be conceptualized as a + * preprocessing step which applies the following function: + * if (blendMode == BlendMode::PREMULTIPLIED) + * out.rgb = in.rgb * planeAlpha + * out.a = in.a * planeAlpha + * + * If the device does not support this operation on a layer which is + * marked Composition::DEVICE, it must request a composition type change + * to Composition::CLIENT upon the next validateDisplay call. + * + * @param alpha is the plane alpha value to apply. + * + * + * SET_LAYER_SIDEBAND_STREAM has this pseudo prototype + * + * setLayerSidebandStream(int32_t streamIndex) + * + * Sets the sideband stream for this layer. If the composition type of the + * given layer is not Composition::SIDEBAND, this call must succeed and + * have no other effect. + * + * @param streamIndex is the new sideband stream. + * + * + * SET_LAYER_SOURCE_CROP has this pseudo prototype + * + * setLayerSourceCrop(FRect crop); + * + * Sets the source crop (the portion of the source buffer which will fill + * the display frame) of the given layer. This crop rectangle must not + * exceed the dimensions of the latched buffer. + * + * If the device is not capable of supporting a true float source crop + * (i.e., it will truncate or round the floats to integers), it must set + * this layer to Composition::CLIENT when crop is non-integral for the + * most accurate rendering. + * + * If the device cannot support float source crops, but still wants to + * handle the layer, it must use the following code (or similar) to + * convert to an integer crop: + * intCrop.left = (int) ceilf(crop.left); + * intCrop.top = (int) ceilf(crop.top); + * intCrop.right = (int) floorf(crop.right); + * intCrop.bottom = (int) floorf(crop.bottom); + * + * @param crop is the new source crop. + * + * + * SET_LAYER_TRANSFORM has this pseudo prototype + * + * Sets the transform (rotation/flip) of the given layer. + * + * setLayerTransform(Transform transform); + * + * @param transform is the new transform. + * + * + * SET_LAYER_VISIBLE_REGION has this pseudo prototype + * + * setLayerVisibleRegion(vec visible); + * + * Specifies the portion of the layer that is visible, including portions + * under translucent areas of other layers. The region is in screen space, + * and must not exceed the dimensions of the screen. + * + * @param visible is the new visible region, in screen space. + * + * + * SET_LAYER_Z_ORDER has this pseudo prototype + * + * setLayerZOrder(uint32_t z); + * + * Sets the desired Z order (height) of the given layer. A layer with a + * greater Z value occludes a layer with a lesser Z value. + * + * @param z is the new Z order. + */ + enum Command : int32_t { + LENGTH_MASK = 0xffff, + OPCODE_SHIFT = 16, + OPCODE_MASK = 0xffff << OPCODE_SHIFT, + + /* special commands */ + SELECT_DISPLAY = 0x000 << OPCODE_SHIFT, + SELECT_LAYER = 0x001 << OPCODE_SHIFT, + + /* value commands (for return values) */ + SET_ERROR = 0x100 << OPCODE_SHIFT, + SET_CHANGED_COMPOSITION_TYPES = 0x101 << OPCODE_SHIFT, + SET_DISPLAY_REQUESTS = 0x102 << OPCODE_SHIFT, + SET_PRESENT_FENCE = 0x103 << OPCODE_SHIFT, + SET_RELEASE_FENCES = 0x104 << OPCODE_SHIFT, + + /* display commands */ + SET_COLOR_TRANSFORM = 0x200 << OPCODE_SHIFT, + SET_CLIENT_TARGET = 0x201 << OPCODE_SHIFT, + SET_OUTPUT_BUFFER = 0x202 << OPCODE_SHIFT, + VALIDATE_DISPLAY = 0x203 << OPCODE_SHIFT, + ACCEPT_DISPLAY_CHANGES = 0x204 << OPCODE_SHIFT, + PRESENT_DISPLAY = 0x205 << OPCODE_SHIFT, + + /* layer commands (VALIDATE_DISPLAY not required) */ + SET_LAYER_CURSOR_POSITION = 0x300 << OPCODE_SHIFT, + SET_LAYER_BUFFER = 0x301 << OPCODE_SHIFT, + SET_LAYER_SURFACE_DAMAGE = 0x302 << OPCODE_SHIFT, + + /* layer state commands (VALIDATE_DISPLAY required) */ + SET_LAYER_BLEND_MODE = 0x400 << OPCODE_SHIFT, + SET_LAYER_COLOR = 0x401 << OPCODE_SHIFT, + SET_LAYER_COMPOSITION_TYPE = 0x402 << OPCODE_SHIFT, + SET_LAYER_DATASPACE = 0x403 << OPCODE_SHIFT, + SET_LAYER_DISPLAY_FRAME = 0x404 << OPCODE_SHIFT, + SET_LAYER_PLANE_ALPHA = 0x405 << OPCODE_SHIFT, + SET_LAYER_SIDEBAND_STREAM = 0x406 << OPCODE_SHIFT, + SET_LAYER_SOURCE_CROP = 0x407 << OPCODE_SHIFT, + SET_LAYER_TRANSFORM = 0x408 << OPCODE_SHIFT, + SET_LAYER_VISIBLE_REGION = 0x409 << OPCODE_SHIFT, + SET_LAYER_Z_ORDER = 0x40a << OPCODE_SHIFT, + + /* 0x800 - 0xfff are reserved for vendor extensions */ + /* 0x1000 - 0xffff are reserved */ + }; +}; diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp index 22f4906d79..0d63c3ca00 100644 --- a/graphics/composer/2.1/default/Android.bp +++ b/graphics/composer/2.1/default/Android.bp @@ -1,17 +1,19 @@ cc_library_shared { name: "android.hardware.graphics.composer@2.1-impl", relative_install_path: "hw", - srcs: ["Hwc.cpp"], + srcs: ["Hwc.cpp", "HwcClient.cpp"], shared_libs: [ "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.composer@2.1", "libbase", "libcutils", + "libfmq", "libhardware", "libhidlbase", "libhidltransport", "libhwbinder", "liblog", + "libsync", "libutils", ], } @@ -19,7 +21,7 @@ cc_library_shared { cc_binary { name: "android.hardware.graphics.composer@2.1-service", relative_install_path: "hw", - srcs: ["service.cpp", "Hwc.cpp"], + srcs: ["service.cpp", "Hwc.cpp", "HwcClient.cpp"], cppflags: ["-DBINDERIZED"], init_rc: ["android.hardware.graphics.composer@2.1-service.rc"], @@ -29,11 +31,19 @@ cc_binary { "libbase", "libbinder", "libcutils", + "libfmq", "libhardware", "libhidlbase", "libhidltransport", "libhwbinder", "liblog", + "libsync", "libutils", ], } + +cc_library_static { + name: "libhwcomposer-command-buffer", + shared_libs: ["android.hardware.graphics.composer@2.1"], + export_include_dirs: ["."], +} diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp index 36c6e54b95..d14de6f9cf 100644 --- a/graphics/composer/2.1/default/Hwc.cpp +++ b/graphics/composer/2.1/default/Hwc.cpp @@ -16,19 +16,12 @@ #define LOG_TAG "HwcPassthrough" -#include #include -#include -#include -#include -#include -#include -#include -#include #include #include "Hwc.h" +#include "HwcClient.h" namespace android { namespace hardware { @@ -37,419 +30,9 @@ namespace composer { namespace V2_1 { namespace implementation { -using android::hardware::graphics::common::V1_0::PixelFormat; -using android::hardware::graphics::common::V1_0::Transform; -using android::hardware::graphics::common::V1_0::Dataspace; -using android::hardware::graphics::common::V1_0::ColorMode; -using android::hardware::graphics::common::V1_0::ColorTransform; -using android::hardware::graphics::common::V1_0::Hdr; - -namespace { - -class HandleImporter { -public: - HandleImporter() : mInitialized(false) {} - - bool initialize() - { - // allow only one client - if (mInitialized) { - return false; - } - - if (!openGralloc()) { - return false; - } - - mInitialized = true; - return true; - } - - void cleanup() - { - if (!mInitialized) { - return; - } - - closeGralloc(); - mInitialized = false; - } - - // In IComposer, any buffer_handle_t is owned by the caller and we need to - // make a clone for hwcomposer2. We also need to translate empty handle - // to nullptr. This function does that, in-place. - bool importBuffer(buffer_handle_t& handle) - { - if (!handle->numFds && !handle->numInts) { - handle = nullptr; - return true; - } - - buffer_handle_t clone = cloneBuffer(handle); - if (!clone) { - return false; - } - - handle = clone; - return true; - } - - void freeBuffer(buffer_handle_t handle) - { - if (!handle) { - return; - } - - releaseBuffer(handle); - } - - bool importFence(const native_handle_t* handle, int& fd) - { - if (handle->numFds == 0) { - fd = -1; - } else if (handle->numFds == 1) { - fd = dup(handle->data[0]); - if (fd < 0) { - ALOGE("failed to dup fence fd %d", handle->data[0]); - return false; - } - } else { - ALOGE("invalid fence handle with %d file descriptors", - handle->numFds); - return false; - } - - return true; - } - - void closeFence(int fd) - { - if (fd >= 0) { - close(fd); - } - } - -private: - bool mInitialized; - - // Some existing gralloc drivers do not support retaining more than once, - // when we are in passthrough mode. -#ifdef BINDERIZED - bool openGralloc() - { - const hw_module_t* module; - int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); - if (err) { - ALOGE("failed to get gralloc module"); - return false; - } - - uint8_t major = (module->module_api_version >> 8) & 0xff; - if (major > 1) { - ALOGE("unknown gralloc module major version %d", major); - return false; - } - - if (major == 1) { - err = gralloc1_open(module, &mDevice); - if (err) { - ALOGE("failed to open gralloc1 device"); - return false; - } - - mRetain = reinterpret_cast( - mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN)); - mRelease = reinterpret_cast( - mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE)); - if (!mRetain || !mRelease) { - ALOGE("invalid gralloc1 device"); - gralloc1_close(mDevice); - return false; - } - } else { - mModule = reinterpret_cast(module); - } - - return true; - } - - void closeGralloc() - { - if (mDevice) { - gralloc1_close(mDevice); - } - } - - buffer_handle_t cloneBuffer(buffer_handle_t handle) - { - native_handle_t* clone = native_handle_clone(handle); - if (!clone) { - ALOGE("failed to clone buffer %p", handle); - return nullptr; - } - - bool err; - if (mDevice) { - err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE); - } else { - err = (mModule->registerBuffer(mModule, clone) != 0); - } - - if (err) { - ALOGE("failed to retain/register buffer %p", clone); - native_handle_close(clone); - native_handle_delete(clone); - return nullptr; - } - - return clone; - } - - void releaseBuffer(buffer_handle_t handle) - { - if (mDevice) { - mRelease(mDevice, handle); - } else { - mModule->unregisterBuffer(mModule, handle); - native_handle_close(handle); - native_handle_delete(const_cast(handle)); - } - } - - // gralloc1 - gralloc1_device_t* mDevice; - GRALLOC1_PFN_RETAIN mRetain; - GRALLOC1_PFN_RELEASE mRelease; - - // gralloc0 - const gralloc_module_t* mModule; -#else - bool openGralloc() { return true; } - void closeGralloc() {} - buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; } - void releaseBuffer(buffer_handle_t) {} -#endif -}; - -HandleImporter sHandleImporter; - -class BufferClone { -public: - BufferClone() : mHandle(nullptr) {} - - BufferClone(BufferClone&& other) - { - mHandle = other.mHandle; - other.mHandle = nullptr; - } - - BufferClone(const BufferClone& other) = delete; - BufferClone& operator=(const BufferClone& other) = delete; - - BufferClone& operator=(buffer_handle_t handle) - { - clear(); - mHandle = handle; - return *this; - } - - ~BufferClone() - { - clear(); - } - -private: - void clear() - { - if (mHandle) { - sHandleImporter.freeBuffer(mHandle); - } - } - - buffer_handle_t mHandle; -}; - -} // anonymous namespace - -class HwcHal : public IComposer { -public: - HwcHal(const hw_module_t* module); - virtual ~HwcHal(); - - // IComposer interface - Return getCapabilities(getCapabilities_cb hidl_cb) override; - Return dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; - Return registerCallback(const sp& callback) override; - Return getMaxVirtualDisplayCount() override; - Return createVirtualDisplay(uint32_t width, uint32_t height, - PixelFormat formatHint, createVirtualDisplay_cb hidl_cb) override; - Return destroyVirtualDisplay(Display display) override; - Return acceptDisplayChanges(Display display) override; - Return createLayer(Display display, - createLayer_cb hidl_cb) override; - Return destroyLayer(Display display, Layer layer) override; - Return getActiveConfig(Display display, - getActiveConfig_cb hidl_cb) override; - Return getChangedCompositionTypes(Display display, - getChangedCompositionTypes_cb hidl_cb) override; - Return getClientTargetSupport(Display display, - uint32_t width, uint32_t height, - PixelFormat format, Dataspace dataspace) override; - Return getColorModes(Display display, - getColorModes_cb hidl_cb) override; - Return getDisplayAttribute(Display display, - Config config, Attribute attribute, - getDisplayAttribute_cb hidl_cb) override; - Return getDisplayConfigs(Display display, - getDisplayConfigs_cb hidl_cb) override; - Return getDisplayName(Display display, - getDisplayName_cb hidl_cb) override; - Return getDisplayRequests(Display display, - getDisplayRequests_cb hidl_cb) override; - Return getDisplayType(Display display, - getDisplayType_cb hidl_cb) override; - Return getDozeSupport(Display display, - getDozeSupport_cb hidl_cb) override; - Return getHdrCapabilities(Display display, - getHdrCapabilities_cb hidl_cb) override; - Return getReleaseFences(Display display, - getReleaseFences_cb hidl_cb) override; - Return presentDisplay(Display display, - presentDisplay_cb hidl_cb) override; - Return setActiveConfig(Display display, Config config) override; - Return setClientTarget(Display display, - const hidl_handle& target, - const hidl_handle& acquireFence, - Dataspace dataspace, const hidl_vec& damage) override; - Return setColorMode(Display display, ColorMode mode) override; - Return setColorTransform(Display display, - const hidl_vec& matrix, ColorTransform hint) override; - Return setOutputBuffer(Display display, - const hidl_handle& buffer, - const hidl_handle& releaseFence) override; - Return setPowerMode(Display display, PowerMode mode) override; - Return setVsyncEnabled(Display display, Vsync enabled) override; - Return validateDisplay(Display display, - validateDisplay_cb hidl_cb) override; - Return setCursorPosition(Display display, - Layer layer, int32_t x, int32_t y) override; - Return setLayerBuffer(Display display, - Layer layer, const hidl_handle& buffer, - const hidl_handle& acquireFence) override; - Return setLayerSurfaceDamage(Display display, - Layer layer, const hidl_vec& damage) override; - Return setLayerBlendMode(Display display, - Layer layer, BlendMode mode) override; - Return setLayerColor(Display display, - Layer layer, const Color& color) override; - Return setLayerCompositionType(Display display, - Layer layer, Composition type) override; - Return setLayerDataspace(Display display, - Layer layer, Dataspace dataspace) override; - Return setLayerDisplayFrame(Display display, - Layer layer, const Rect& frame) override; - Return setLayerPlaneAlpha(Display display, - Layer layer, float alpha) override; - Return setLayerSidebandStream(Display display, - Layer layer, const hidl_handle& stream) override; - Return setLayerSourceCrop(Display display, - Layer layer, const FRect& crop) override; - Return setLayerTransform(Display display, - Layer layer, Transform transform) override; - Return setLayerVisibleRegion(Display display, - Layer layer, const hidl_vec& visible) override; - Return setLayerZOrder(Display display, - Layer layer, uint32_t z) override; - -private: - void initCapabilities(); - - template - void initDispatch(T& func, hwc2_function_descriptor_t desc); - void initDispatch(); - - bool hasCapability(Capability capability) const; - - static void hotplugHook(hwc2_callback_data_t callbackData, - hwc2_display_t display, int32_t connected); - static void refreshHook(hwc2_callback_data_t callbackData, - hwc2_display_t display); - static void vsyncHook(hwc2_callback_data_t callbackData, - hwc2_display_t display, int64_t timestamp); - - hwc2_device_t* mDevice; - - std::unordered_set mCapabilities; - - struct { - HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges; - HWC2_PFN_CREATE_LAYER createLayer; - HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay; - HWC2_PFN_DESTROY_LAYER destroyLayer; - HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay; - HWC2_PFN_DUMP dump; - HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig; - HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes; - HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport; - HWC2_PFN_GET_COLOR_MODES getColorModes; - HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute; - HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs; - HWC2_PFN_GET_DISPLAY_NAME getDisplayName; - HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests; - HWC2_PFN_GET_DISPLAY_TYPE getDisplayType; - HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport; - HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities; - HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount; - HWC2_PFN_GET_RELEASE_FENCES getReleaseFences; - HWC2_PFN_PRESENT_DISPLAY presentDisplay; - HWC2_PFN_REGISTER_CALLBACK registerCallback; - HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig; - HWC2_PFN_SET_CLIENT_TARGET setClientTarget; - HWC2_PFN_SET_COLOR_MODE setColorMode; - HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform; - HWC2_PFN_SET_CURSOR_POSITION setCursorPosition; - HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode; - HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer; - HWC2_PFN_SET_LAYER_COLOR setLayerColor; - HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType; - HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace; - HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame; - HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha; - HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream; - HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop; - HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage; - HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform; - HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion; - HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder; - HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer; - HWC2_PFN_SET_POWER_MODE setPowerMode; - HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled; - HWC2_PFN_VALIDATE_DISPLAY validateDisplay; - } mDispatch; - - // cloned buffers for a display - struct DisplayBuffers { - BufferClone ClientTarget; - BufferClone OutputBuffer; - - std::unordered_map LayerBuffers; - std::unordered_map LayerSidebandStreams; - }; - - std::mutex mCallbackMutex; - sp mCallback; - - std::mutex mDisplayMutex; - std::unordered_map mDisplays; -}; - HwcHal::HwcHal(const hw_module_t* module) : mDevice(nullptr), mDispatch() { - if (!sHandleImporter.initialize()) { - LOG_ALWAYS_FATAL("failed to initialize handle importer"); - } - int status = hwc2_open(module, &mDevice); if (status) { LOG_ALWAYS_FATAL("failed to open hwcomposer2 device: %s", @@ -463,8 +46,6 @@ HwcHal::HwcHal(const hw_module_t* module) HwcHal::~HwcHal() { hwc2_close(mDevice); - mDisplays.clear(); - sHandleImporter.cleanup(); } void HwcHal::initCapabilities() @@ -599,694 +180,509 @@ Return HwcHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) return Void(); } +Return HwcHal::createClient(createClient_cb hidl_cb) +{ + Error err = Error::NONE; + sp client; + + { + std::lock_guard lock(mClientMutex); + + // only one client is allowed + if (mClient == nullptr) { + client = new HwcClient(*this); + mClient = client; + } else { + err = Error::NO_RESOURCES; + } + } + + hidl_cb(err, client); + + return Void(); +} + +sp HwcHal::getClient() +{ + std::lock_guard lock(mClientMutex); + return (mClient != nullptr) ? mClient.promote() : nullptr; +} + +void HwcHal::removeClient() +{ + std::lock_guard lock(mClientMutex); + mClient = nullptr; +} + void HwcHal::hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected) { auto hal = reinterpret_cast(callbackData); - - { - std::lock_guard lock(hal->mDisplayMutex); - - if (connected == HWC2_CONNECTION_CONNECTED) { - hal->mDisplays.emplace(display, DisplayBuffers()); - } else if (connected == HWC2_CONNECTION_DISCONNECTED) { - hal->mDisplays.erase(display); - } + auto client = hal->getClient(); + if (client != nullptr) { + client->onHotplug(display, + static_cast(connected)); } - - hal->mCallback->onHotplug(display, - static_cast(connected)); } void HwcHal::refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) { auto hal = reinterpret_cast(callbackData); - hal->mCallback->onRefresh(display); + auto client = hal->getClient(); + if (client != nullptr) { + client->onRefresh(display); + } } void HwcHal::vsyncHook(hwc2_callback_data_t callbackData, hwc2_display_t display, int64_t timestamp) { auto hal = reinterpret_cast(callbackData); - hal->mCallback->onVsync(display, timestamp); + auto client = hal->getClient(); + if (client != nullptr) { + client->onVsync(display, timestamp); + } } -Return HwcHal::registerCallback(const sp& callback) +void HwcHal::enableCallback(bool enable) { - std::lock_guard lock(mCallbackMutex); - - mCallback = callback; - - mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, - reinterpret_cast(hotplugHook)); - mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, - reinterpret_cast(refreshHook)); - mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, - reinterpret_cast(vsyncHook)); - - return Void(); + if (enable) { + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, + reinterpret_cast(hotplugHook)); + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, + reinterpret_cast(refreshHook)); + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, + reinterpret_cast(vsyncHook)); + } else { + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, + nullptr); + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, + nullptr); + mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, + nullptr); + } } -Return HwcHal::getMaxVirtualDisplayCount() +uint32_t HwcHal::getMaxVirtualDisplayCount() { return mDispatch.getMaxVirtualDisplayCount(mDevice); } -Return HwcHal::createVirtualDisplay(uint32_t width, uint32_t height, - PixelFormat formatHint, createVirtualDisplay_cb hidl_cb) +Error HwcHal::createVirtualDisplay(uint32_t width, uint32_t height, + PixelFormat& format, Display& display) { - int32_t format = static_cast(formatHint); - hwc2_display_t display; - auto error = mDispatch.createVirtualDisplay(mDevice, width, height, - &format, &display); - if (error == HWC2_ERROR_NONE) { - std::lock_guard lock(mDisplayMutex); + int32_t hwc_format = static_cast(format); + int32_t err = mDispatch.createVirtualDisplay(mDevice, width, height, + &hwc_format, &display); + format = static_cast(hwc_format); - mDisplays.emplace(display, DisplayBuffers()); - } - - hidl_cb(static_cast(error), display, - static_cast(format)); - - return Void(); + return static_cast(err); } -Return HwcHal::destroyVirtualDisplay(Display display) +Error HwcHal::destroyVirtualDisplay(Display display) { - auto error = mDispatch.destroyVirtualDisplay(mDevice, display); - if (error == HWC2_ERROR_NONE) { - std::lock_guard lock(mDisplayMutex); - - mDisplays.erase(display); - } - - return static_cast(error); + int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display); + return static_cast(err); } -Return HwcHal::acceptDisplayChanges(Display display) +Error HwcHal::createLayer(Display display, Layer& layer) { - auto error = mDispatch.acceptDisplayChanges(mDevice, display); - return static_cast(error); + int32_t err = mDispatch.createLayer(mDevice, display, &layer); + return static_cast(err); } -Return HwcHal::createLayer(Display display, createLayer_cb hidl_cb) +Error HwcHal::destroyLayer(Display display, Layer layer) { - hwc2_layer_t layer; - auto error = mDispatch.createLayer(mDevice, display, &layer); - - hidl_cb(static_cast(error), layer); - - return Void(); + int32_t err = mDispatch.destroyLayer(mDevice, display, layer); + return static_cast(err); } -Return HwcHal::destroyLayer(Display display, Layer layer) +Error HwcHal::getActiveConfig(Display display, Config& config) { - auto error = mDispatch.destroyLayer(mDevice, display, layer); - if (error == HWC2_ERROR_NONE) { - std::lock_guard lock(mDisplayMutex); - - auto dpy = mDisplays.find(display); - dpy->second.LayerBuffers.erase(layer); - dpy->second.LayerSidebandStreams.erase(layer); - } - - return static_cast(error); + int32_t err = mDispatch.getActiveConfig(mDevice, display, &config); + return static_cast(err); } -Return HwcHal::getActiveConfig(Display display, - getActiveConfig_cb hidl_cb) -{ - hwc2_config_t config; - auto error = mDispatch.getActiveConfig(mDevice, display, &config); - - hidl_cb(static_cast(error), config); - - return Void(); -} - -Return HwcHal::getChangedCompositionTypes(Display display, - getChangedCompositionTypes_cb hidl_cb) -{ - uint32_t count = 0; - auto error = mDispatch.getChangedCompositionTypes(mDevice, display, - &count, nullptr, nullptr); - if (error != HWC2_ERROR_NONE) { - count = 0; - } - - std::vector layers(count); - std::vector types(count); - error = mDispatch.getChangedCompositionTypes(mDevice, display, - &count, layers.data(), - reinterpret_cast::type*>( - types.data())); - if (error != HWC2_ERROR_NONE) { - count = 0; - } - layers.resize(count); - types.resize(count); - - hidl_vec layers_reply; - layers_reply.setToExternal(layers.data(), layers.size()); - - hidl_vec types_reply; - types_reply.setToExternal(types.data(), types.size()); - - hidl_cb(static_cast(error), layers_reply, types_reply); - - return Void(); -} - -Return HwcHal::getClientTargetSupport(Display display, +Error HwcHal::getClientTargetSupport(Display display, uint32_t width, uint32_t height, PixelFormat format, Dataspace dataspace) { - auto error = mDispatch.getClientTargetSupport(mDevice, display, + int32_t err = mDispatch.getClientTargetSupport(mDevice, display, width, height, static_cast(format), static_cast(dataspace)); - return static_cast(error); + return static_cast(err); } -Return HwcHal::getColorModes(Display display, getColorModes_cb hidl_cb) +Error HwcHal::getColorModes(Display display, hidl_vec& modes) { uint32_t count = 0; - auto error = mDispatch.getColorModes(mDevice, display, &count, nullptr); - if (error != HWC2_ERROR_NONE) { - count = 0; + int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr); + if (err != HWC2_ERROR_NONE) { + return static_cast(err); } - std::vector modes(count); - error = mDispatch.getColorModes(mDevice, display, &count, + modes.resize(count); + err = mDispatch.getColorModes(mDevice, display, &count, reinterpret_cast::type*>( modes.data())); - if (error != HWC2_ERROR_NONE) { - count = 0; + if (err != HWC2_ERROR_NONE) { + modes = hidl_vec(); + return static_cast(err); } - modes.resize(count); - hidl_vec modes_reply; - modes_reply.setToExternal(modes.data(), modes.size()); - hidl_cb(static_cast(error), modes_reply); - - return Void(); + return Error::NONE; } -Return HwcHal::getDisplayAttribute(Display display, - Config config, Attribute attribute, - getDisplayAttribute_cb hidl_cb) +Error HwcHal::getDisplayAttribute(Display display, Config config, + IComposerClient::Attribute attribute, int32_t& value) { - int32_t value; - auto error = mDispatch.getDisplayAttribute(mDevice, display, config, + int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config, static_cast(attribute), &value); - - hidl_cb(static_cast(error), value); - - return Void(); + return static_cast(err); } -Return HwcHal::getDisplayConfigs(Display display, - getDisplayConfigs_cb hidl_cb) +Error HwcHal::getDisplayConfigs(Display display, hidl_vec& configs) { uint32_t count = 0; - auto error = mDispatch.getDisplayConfigs(mDevice, display, + int32_t err = mDispatch.getDisplayConfigs(mDevice, display, &count, nullptr); - if (error != HWC2_ERROR_NONE) { - count = 0; + if (err != HWC2_ERROR_NONE) { + return static_cast(err); } - std::vector configs(count); - error = mDispatch.getDisplayConfigs(mDevice, display, - &count, configs.data()); - if (error != HWC2_ERROR_NONE) { - count = 0; - } configs.resize(count); + err = mDispatch.getDisplayConfigs(mDevice, display, + &count, configs.data()); + if (err != HWC2_ERROR_NONE) { + configs = hidl_vec(); + return static_cast(err); + } - hidl_vec configs_reply; - configs_reply.setToExternal(configs.data(), configs.size()); - hidl_cb(static_cast(error), configs_reply); - - return Void(); + return Error::NONE; } -Return HwcHal::getDisplayName(Display display, - getDisplayName_cb hidl_cb) +Error HwcHal::getDisplayName(Display display, hidl_string& name) { uint32_t count = 0; - auto error = mDispatch.getDisplayName(mDevice, display, &count, nullptr); - if (error != HWC2_ERROR_NONE) { - count = 0; + int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr); + if (err != HWC2_ERROR_NONE) { + return static_cast(err); } - std::vector name(count + 1); - error = mDispatch.getDisplayName(mDevice, display, &count, name.data()); - if (error != HWC2_ERROR_NONE) { - count = 0; + std::vector buf(count + 1); + err = mDispatch.getDisplayName(mDevice, display, &count, buf.data()); + if (err != HWC2_ERROR_NONE) { + return static_cast(err); } - name.resize(count + 1); - name[count] = '\0'; + buf.resize(count + 1); + buf[count] = '\0'; - hidl_string name_reply; - name_reply.setToExternal(name.data(), count); - hidl_cb(static_cast(error), name_reply); + name = buf.data(); - return Void(); + return Error::NONE; } -Return HwcHal::getDisplayRequests(Display display, - getDisplayRequests_cb hidl_cb) +Error HwcHal::getDisplayType(Display display, IComposerClient::DisplayType& type) +{ + int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID; + int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type); + type = static_cast(hwc_type); + + return static_cast(err); +} + +Error HwcHal::getDozeSupport(Display display, bool& support) +{ + int32_t hwc_support = 0; + int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support); + support = hwc_support; + + return static_cast(err); +} + +Error HwcHal::getHdrCapabilities(Display display, hidl_vec& types, + float& maxLuminance, float& maxAverageLuminance, float& minLuminance) { - int32_t display_reqs; uint32_t count = 0; - auto error = mDispatch.getDisplayRequests(mDevice, display, - &display_reqs, &count, nullptr, nullptr); - if (error != HWC2_ERROR_NONE) { - count = 0; + int32_t err = mDispatch.getHdrCapabilities(mDevice, display, &count, + nullptr, &maxLuminance, &maxAverageLuminance, &minLuminance); + if (err != HWC2_ERROR_NONE) { + return static_cast(err); } - std::vector layers(count); - std::vector layer_reqs(count); - error = mDispatch.getDisplayRequests(mDevice, display, - &display_reqs, &count, layers.data(), layer_reqs.data()); - if (error != HWC2_ERROR_NONE) { - count = 0; - } - layers.resize(count); - layer_reqs.resize(count); - - hidl_vec layers_reply; - layers_reply.setToExternal(layers.data(), layers.size()); - - hidl_vec layer_reqs_reply; - layer_reqs_reply.setToExternal( - reinterpret_cast(layer_reqs.data()), - layer_reqs.size()); - - hidl_cb(static_cast(error), display_reqs, - layers_reply, layer_reqs_reply); - - return Void(); -} - -Return HwcHal::getDisplayType(Display display, - getDisplayType_cb hidl_cb) -{ - int32_t type; - auto error = mDispatch.getDisplayType(mDevice, display, &type); - - hidl_cb(static_cast(error), static_cast(type)); - - return Void(); -} - -Return HwcHal::getDozeSupport(Display display, - getDozeSupport_cb hidl_cb) -{ - int32_t support; - auto error = mDispatch.getDozeSupport(mDevice, display, &support); - - hidl_cb(static_cast(error), support); - - return Void(); -} - -Return HwcHal::getHdrCapabilities(Display display, - getHdrCapabilities_cb hidl_cb) -{ - float max_lumi, max_avg_lumi, min_lumi; - uint32_t count = 0; - auto error = mDispatch.getHdrCapabilities(mDevice, display, - &count, nullptr, &max_lumi, &max_avg_lumi, &min_lumi); - if (error != HWC2_ERROR_NONE) { - count = 0; - } - - std::vector types(count); - error = mDispatch.getHdrCapabilities(mDevice, display, &count, - reinterpret_cast::type*>(types.data()), - &max_lumi, &max_avg_lumi, &min_lumi); - if (error != HWC2_ERROR_NONE) { - count = 0; - } types.resize(count); + err = mDispatch.getHdrCapabilities(mDevice, display, &count, + reinterpret_cast::type*>(types.data()), + &maxLuminance, &maxAverageLuminance, &minLuminance); + if (err != HWC2_ERROR_NONE) { + return static_cast(err); + } - hidl_vec types_reply; - types_reply.setToExternal(types.data(), types.size()); - hidl_cb(static_cast(error), types_reply, - max_lumi, max_avg_lumi, min_lumi); - - return Void(); + return Error::NONE; } -Return HwcHal::getReleaseFences(Display display, - getReleaseFences_cb hidl_cb) +Error HwcHal::setActiveConfig(Display display, Config config) { - uint32_t count = 0; - auto error = mDispatch.getReleaseFences(mDevice, display, - &count, nullptr, nullptr); - if (error != HWC2_ERROR_NONE) { - count = 0; - } - - std::vector layers(count); - std::vector fences(count); - error = mDispatch.getReleaseFences(mDevice, display, - &count, layers.data(), fences.data()); - if (error != HWC2_ERROR_NONE) { - count = 0; - } - layers.resize(count); - fences.resize(count); - - // filter out layers with release fence -1 - std::vector filtered_layers; - std::vector filtered_fences; - for (size_t i = 0; i < layers.size(); i++) { - if (fences[i] >= 0) { - filtered_layers.push_back(layers[i]); - filtered_fences.push_back(fences[i]); - } - } - - hidl_vec layers_reply; - native_handle_t* fences_reply = - native_handle_create(filtered_fences.size(), 0); - if (fences_reply) { - layers_reply.setToExternal(filtered_layers.data(), - filtered_layers.size()); - memcpy(fences_reply->data, filtered_fences.data(), - sizeof(int) * filtered_fences.size()); - - hidl_cb(static_cast(error), layers_reply, fences_reply); - - native_handle_close(fences_reply); - native_handle_delete(fences_reply); - } else { - NATIVE_HANDLE_DECLARE_STORAGE(fences_storage, 0, 0); - fences_reply = native_handle_init(fences_storage, 0, 0); - - hidl_cb(Error::NO_RESOURCES, layers_reply, fences_reply); - - for (auto fence : filtered_fences) { - close(fence); - } - } - - return Void(); + int32_t err = mDispatch.setActiveConfig(mDevice, display, config); + return static_cast(err); } -Return HwcHal::presentDisplay(Display display, - presentDisplay_cb hidl_cb) +Error HwcHal::setColorMode(Display display, ColorMode mode) { - int32_t fence = -1; - auto error = mDispatch.presentDisplay(mDevice, display, &fence); - - NATIVE_HANDLE_DECLARE_STORAGE(fence_storage, 1, 0); - native_handle_t* fence_reply; - if (fence >= 0) { - fence_reply = native_handle_init(fence_storage, 1, 0); - fence_reply->data[0] = fence; - } else { - fence_reply = native_handle_init(fence_storage, 0, 0); - } - - hidl_cb(static_cast(error), fence_reply); - - if (fence >= 0) { - close(fence); - } - - return Void(); -} - -Return HwcHal::setActiveConfig(Display display, Config config) -{ - auto error = mDispatch.setActiveConfig(mDevice, display, config); - return static_cast(error); -} - -Return HwcHal::setClientTarget(Display display, - const hidl_handle& target, - const hidl_handle& acquireFence, - Dataspace dataspace, const hidl_vec& damage) -{ - const native_handle_t* targetHandle = target.getNativeHandle(); - if (!sHandleImporter.importBuffer(targetHandle)) { - return Error::NO_RESOURCES; - } - - int32_t fence; - if (!sHandleImporter.importFence(acquireFence, fence)) { - sHandleImporter.freeBuffer(targetHandle); - return Error::NO_RESOURCES; - } - - hwc_region_t damage_region = { damage.size(), - reinterpret_cast(&damage[0]) }; - - int32_t error = mDispatch.setClientTarget(mDevice, display, - targetHandle, fence, static_cast(dataspace), - damage_region); - if (error == HWC2_ERROR_NONE) { - std::lock_guard lock(mDisplayMutex); - - auto dpy = mDisplays.find(display); - dpy->second.ClientTarget = targetHandle; - } else { - sHandleImporter.freeBuffer(target); - sHandleImporter.closeFence(fence); - } - - return static_cast(error); -} - -Return HwcHal::setColorMode(Display display, ColorMode mode) -{ - auto error = mDispatch.setColorMode(mDevice, display, + int32_t err = mDispatch.setColorMode(mDevice, display, static_cast(mode)); - return static_cast(error); + return static_cast(err); } -Return HwcHal::setColorTransform(Display display, - const hidl_vec& matrix, ColorTransform hint) +Error HwcHal::setPowerMode(Display display, IComposerClient::PowerMode mode) { - auto error = mDispatch.setColorTransform(mDevice, display, - &matrix[0], static_cast(hint)); - return static_cast(error); -} - -Return HwcHal::setOutputBuffer(Display display, - const hidl_handle& buffer, - const hidl_handle& releaseFence) -{ - const native_handle_t* bufferHandle = buffer.getNativeHandle(); - if (!sHandleImporter.importBuffer(bufferHandle)) { - return Error::NO_RESOURCES; - } - - int32_t fence; - if (!sHandleImporter.importFence(releaseFence, fence)) { - sHandleImporter.freeBuffer(bufferHandle); - return Error::NO_RESOURCES; - } - - int32_t error = mDispatch.setOutputBuffer(mDevice, - display, bufferHandle, fence); - if (error == HWC2_ERROR_NONE) { - std::lock_guard lock(mDisplayMutex); - - auto dpy = mDisplays.find(display); - dpy->second.OutputBuffer = bufferHandle; - } else { - sHandleImporter.freeBuffer(bufferHandle); - } - - // unlike in setClientTarget, fence is owned by us and is always closed - sHandleImporter.closeFence(fence); - - return static_cast(error); -} - -Return HwcHal::setPowerMode(Display display, PowerMode mode) -{ - auto error = mDispatch.setPowerMode(mDevice, display, + int32_t err = mDispatch.setPowerMode(mDevice, display, static_cast(mode)); - return static_cast(error); + return static_cast(err); } -Return HwcHal::setVsyncEnabled(Display display, - Vsync enabled) +Error HwcHal::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) { - auto error = mDispatch.setVsyncEnabled(mDevice, display, + int32_t err = mDispatch.setVsyncEnabled(mDevice, display, static_cast(enabled)); - return static_cast(error); + return static_cast(err); } -Return HwcHal::validateDisplay(Display display, - validateDisplay_cb hidl_cb) +Error HwcHal::setColorTransform(Display display, const float* matrix, + int32_t hint) +{ + int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint); + return static_cast(err); +} + +Error HwcHal::setClientTarget(Display display, buffer_handle_t target, + int32_t acquireFence, int32_t dataspace, + const std::vector& damage) +{ + hwc_region region = { damage.size(), damage.data() }; + int32_t err = mDispatch.setClientTarget(mDevice, display, target, + acquireFence, dataspace, region); + return static_cast(err); +} + +Error HwcHal::setOutputBuffer(Display display, buffer_handle_t buffer, + int32_t releaseFence) +{ + int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer, + releaseFence); + // unlike in setClientTarget, releaseFence is owned by us + if (err == HWC2_ERROR_NONE && releaseFence >= 0) { + close(releaseFence); + } + + return static_cast(err); +} + +Error HwcHal::validateDisplay(Display display, + std::vector& changedLayers, + std::vector& compositionTypes, + uint32_t& displayRequestMask, + std::vector& requestedLayers, + std::vector& requestMasks) { uint32_t types_count = 0; uint32_t reqs_count = 0; - auto error = mDispatch.validateDisplay(mDevice, display, + int32_t err = mDispatch.validateDisplay(mDevice, display, &types_count, &reqs_count); - - hidl_cb(static_cast(error), types_count, reqs_count); - - return Void(); -} - -Return HwcHal::setCursorPosition(Display display, - Layer layer, int32_t x, int32_t y) -{ - auto error = mDispatch.setCursorPosition(mDevice, display, layer, x, y); - return static_cast(error); -} - -Return HwcHal::setLayerBuffer(Display display, - Layer layer, const hidl_handle& buffer, - const hidl_handle& acquireFence) -{ - const native_handle_t* bufferHandle = buffer.getNativeHandle(); - if (!sHandleImporter.importBuffer(bufferHandle)) { - return Error::NO_RESOURCES; + if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) { + return static_cast(err); } - int32_t fence; - if (!sHandleImporter.importFence(acquireFence, fence)) { - sHandleImporter.freeBuffer(bufferHandle); - return Error::NO_RESOURCES; + err = mDispatch.getChangedCompositionTypes(mDevice, display, + &types_count, nullptr, nullptr); + if (err != HWC2_ERROR_NONE) { + return static_cast(err); } - int32_t error = mDispatch.setLayerBuffer(mDevice, - display, layer, bufferHandle, fence); - if (error == HWC2_ERROR_NONE) { - std::lock_guard lock(mDisplayMutex); - - auto dpy = mDisplays.find(display); - dpy->second.LayerBuffers[layer] = bufferHandle; - } else { - sHandleImporter.freeBuffer(bufferHandle); - sHandleImporter.closeFence(fence); + changedLayers.resize(types_count); + compositionTypes.resize(types_count); + err = mDispatch.getChangedCompositionTypes(mDevice, display, + &types_count, changedLayers.data(), + reinterpret_cast< + std::underlying_type::type*>( + compositionTypes.data())); + if (err != HWC2_ERROR_NONE) { + changedLayers.clear(); + compositionTypes.clear(); + return static_cast(err); } - return static_cast(error); + int32_t display_reqs = 0; + err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs, + &reqs_count, nullptr, nullptr); + if (err != HWC2_ERROR_NONE) { + changedLayers.clear(); + compositionTypes.clear(); + return static_cast(err); + } + + requestedLayers.resize(reqs_count); + requestMasks.resize(reqs_count); + err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs, + &reqs_count, requestedLayers.data(), + reinterpret_cast(requestMasks.data())); + if (err != HWC2_ERROR_NONE) { + changedLayers.clear(); + compositionTypes.clear(); + + requestedLayers.clear(); + requestMasks.clear(); + return static_cast(err); + } + + displayRequestMask = display_reqs; + + return static_cast(err); } -Return HwcHal::setLayerSurfaceDamage(Display display, - Layer layer, const hidl_vec& damage) +Error HwcHal::acceptDisplayChanges(Display display) { - hwc_region_t damage_region = { damage.size(), - reinterpret_cast(&damage[0]) }; - - auto error = mDispatch.setLayerSurfaceDamage(mDevice, display, layer, - damage_region); - return static_cast(error); + int32_t err = mDispatch.acceptDisplayChanges(mDevice, display); + return static_cast(err); } -Return HwcHal::setLayerBlendMode(Display display, - Layer layer, BlendMode mode) +Error HwcHal::presentDisplay(Display display, int32_t& presentFence, + std::vector& layers, std::vector& releaseFences) { - auto error = mDispatch.setLayerBlendMode(mDevice, display, layer, - static_cast(mode)); - return static_cast(error); + presentFence = -1; + int32_t err = mDispatch.presentDisplay(mDevice, display, &presentFence); + if (err != HWC2_ERROR_NONE) { + return static_cast(err); + } + + uint32_t count = 0; + err = mDispatch.getReleaseFences(mDevice, display, &count, + nullptr, nullptr); + if (err != HWC2_ERROR_NONE) { + ALOGW("failed to get release fences"); + return Error::NONE; + } + + layers.resize(count); + releaseFences.resize(count); + err = mDispatch.getReleaseFences(mDevice, display, &count, + layers.data(), releaseFences.data()); + if (err != HWC2_ERROR_NONE) { + ALOGW("failed to get release fences"); + layers.clear(); + releaseFences.clear(); + return Error::NONE; + } + + return static_cast(err); } -Return HwcHal::setLayerColor(Display display, - Layer layer, const Color& color) +Error HwcHal::setLayerCursorPosition(Display display, Layer layer, + int32_t x, int32_t y) +{ + int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y); + return static_cast(err); +} + +Error HwcHal::setLayerBuffer(Display display, Layer layer, + buffer_handle_t buffer, int32_t acquireFence) +{ + int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer, + buffer, acquireFence); + return static_cast(err); +} + +Error HwcHal::setLayerSurfaceDamage(Display display, Layer layer, + const std::vector& damage) +{ + hwc_region region = { damage.size(), damage.data() }; + int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer, + region); + return static_cast(err); +} + +Error HwcHal::setLayerBlendMode(Display display, Layer layer, int32_t mode) +{ + int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode); + return static_cast(err); +} + +Error HwcHal::setLayerColor(Display display, Layer layer, + IComposerClient::Color color) { hwc_color_t hwc_color{color.r, color.g, color.b, color.a}; - auto error = mDispatch.setLayerColor(mDevice, display, layer, hwc_color); - return static_cast(error); + int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color); + return static_cast(err); } -Return HwcHal::setLayerCompositionType(Display display, - Layer layer, Composition type) +Error HwcHal::setLayerCompositionType(Display display, Layer layer, + int32_t type) { - auto error = mDispatch.setLayerCompositionType(mDevice, display, layer, - static_cast(type)); - return static_cast(error); + int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer, + type); + return static_cast(err); } -Return HwcHal::setLayerDataspace(Display display, - Layer layer, Dataspace dataspace) +Error HwcHal::setLayerDataspace(Display display, Layer layer, + int32_t dataspace) { - auto error = mDispatch.setLayerDataspace(mDevice, display, layer, - static_cast(dataspace)); - return static_cast(error); + int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer, + dataspace); + return static_cast(err); } -Return HwcHal::setLayerDisplayFrame(Display display, - Layer layer, const Rect& frame) +Error HwcHal::setLayerDisplayFrame(Display display, Layer layer, + const hwc_rect_t& frame) { - hwc_rect_t hwc_frame{frame.left, frame.top, frame.right, frame.bottom}; - auto error = mDispatch.setLayerDisplayFrame(mDevice, display, layer, - hwc_frame); - return static_cast(error); + int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer, + frame); + return static_cast(err); } -Return HwcHal::setLayerPlaneAlpha(Display display, - Layer layer, float alpha) +Error HwcHal::setLayerPlaneAlpha(Display display, Layer layer, float alpha) { - auto error = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, alpha); - return static_cast(error); + int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, + alpha); + return static_cast(err); } -Return HwcHal::setLayerSidebandStream(Display display, - Layer layer, const hidl_handle& stream) +Error HwcHal::setLayerSidebandStream(Display display, Layer layer, + buffer_handle_t stream) { - const native_handle_t* streamHandle = stream.getNativeHandle(); - if (!sHandleImporter.importBuffer(streamHandle)) { - return Error::NO_RESOURCES; - } - - int32_t error = mDispatch.setLayerSidebandStream(mDevice, - display, layer, streamHandle); - if (error == HWC2_ERROR_NONE) { - std::lock_guard lock(mDisplayMutex); - - auto dpy = mDisplays.find(display); - dpy->second.LayerSidebandStreams[layer] = streamHandle; - } else { - sHandleImporter.freeBuffer(streamHandle); - } - - return static_cast(error); + int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer, + stream); + return static_cast(err); } -Return HwcHal::setLayerSourceCrop(Display display, - Layer layer, const FRect& crop) +Error HwcHal::setLayerSourceCrop(Display display, Layer layer, + const hwc_frect_t& crop) { - hwc_frect_t hwc_crop{crop.left, crop.top, crop.right, crop.bottom}; - auto error = mDispatch.setLayerSourceCrop(mDevice, display, layer, - hwc_crop); - return static_cast(error); + int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop); + return static_cast(err); } -Return HwcHal::setLayerTransform(Display display, - Layer layer, Transform transform) +Error HwcHal::setLayerTransform(Display display, Layer layer, + int32_t transform) { - auto error = mDispatch.setLayerTransform(mDevice, display, layer, - static_cast(transform)); - return static_cast(error); + int32_t err = mDispatch.setLayerTransform(mDevice, display, layer, + transform); + return static_cast(err); } -Return HwcHal::setLayerVisibleRegion(Display display, - Layer layer, const hidl_vec& visible) +Error HwcHal::setLayerVisibleRegion(Display display, Layer layer, + const std::vector& visible) { - hwc_region_t visible_region = { visible.size(), - reinterpret_cast(&visible[0]) }; - - auto error = mDispatch.setLayerVisibleRegion(mDevice, display, layer, - visible_region); - return static_cast(error); + hwc_region_t region = { visible.size(), visible.data() }; + int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer, + region); + return static_cast(err); } -Return HwcHal::setLayerZOrder(Display display, - Layer layer, uint32_t z) +Error HwcHal::setLayerZOrder(Display display, Layer layer, uint32_t z) { - auto error = mDispatch.setLayerZOrder(mDevice, display, layer, z); - return static_cast(error); + int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z); + return static_cast(err); } IComposer* HIDL_FETCH_IComposer(const char*) diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h index de69417acd..89ac4f7d2d 100644 --- a/graphics/composer/2.1/default/Hwc.h +++ b/graphics/composer/2.1/default/Hwc.h @@ -17,7 +17,12 @@ #ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H #define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H +#include +#include +#include + #include +#include namespace android { namespace hardware { @@ -26,6 +31,172 @@ namespace composer { namespace V2_1 { namespace implementation { +using android::hardware::graphics::common::V1_0::PixelFormat; +using android::hardware::graphics::common::V1_0::Transform; +using android::hardware::graphics::common::V1_0::Dataspace; +using android::hardware::graphics::common::V1_0::ColorMode; +using android::hardware::graphics::common::V1_0::ColorTransform; +using android::hardware::graphics::common::V1_0::Hdr; + +class HwcClient; + +class HwcHal : public IComposer { +public: + HwcHal(const hw_module_t* module); + virtual ~HwcHal(); + + // IComposer interface + Return getCapabilities(getCapabilities_cb hidl_cb) override; + Return dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; + Return createClient(createClient_cb hidl_cb) override; + + bool hasCapability(Capability capability) const; + + void removeClient(); + + void enableCallback(bool enable); + + uint32_t getMaxVirtualDisplayCount(); + Error createVirtualDisplay(uint32_t width, uint32_t height, + PixelFormat& format, Display& display); + Error destroyVirtualDisplay(Display display); + + Error createLayer(Display display, Layer& layer); + Error destroyLayer(Display display, Layer layer); + + Error getActiveConfig(Display display, Config& config); + Error getClientTargetSupport(Display display, + uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace); + Error getColorModes(Display display, hidl_vec& modes); + Error getDisplayAttribute(Display display, Config config, + IComposerClient::Attribute attribute, int32_t& value); + Error getDisplayConfigs(Display display, hidl_vec& configs); + Error getDisplayName(Display display, hidl_string& name); + Error getDisplayType(Display display, IComposerClient::DisplayType& type); + Error getDozeSupport(Display display, bool& support); + Error getHdrCapabilities(Display display, hidl_vec& types, + float& maxLuminance, float& maxAverageLuminance, + float& minLuminance); + + Error setActiveConfig(Display display, Config config); + Error setColorMode(Display display, ColorMode mode); + Error setPowerMode(Display display, IComposerClient::PowerMode mode); + Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled); + + Error setColorTransform(Display display, const float* matrix, + int32_t hint); + Error setClientTarget(Display display, buffer_handle_t target, + int32_t acquireFence, int32_t dataspace, + const std::vector& damage); + Error setOutputBuffer(Display display, buffer_handle_t buffer, + int32_t releaseFence); + Error validateDisplay(Display display, + std::vector& changedLayers, + std::vector& compositionTypes, + uint32_t& displayRequestMask, + std::vector& requestedLayers, + std::vector& requestMasks); + Error acceptDisplayChanges(Display display); + Error presentDisplay(Display display, int32_t& presentFence, + std::vector& layers, std::vector& releaseFences); + + Error setLayerCursorPosition(Display display, Layer layer, + int32_t x, int32_t y); + Error setLayerBuffer(Display display, Layer layer, + buffer_handle_t buffer, int32_t acquireFence); + Error setLayerSurfaceDamage(Display display, Layer layer, + const std::vector& damage); + Error setLayerBlendMode(Display display, Layer layer, int32_t mode); + Error setLayerColor(Display display, Layer layer, + IComposerClient::Color color); + Error setLayerCompositionType(Display display, Layer layer, + int32_t type); + Error setLayerDataspace(Display display, Layer layer, + int32_t dataspace); + Error setLayerDisplayFrame(Display display, Layer layer, + const hwc_rect_t& frame); + Error setLayerPlaneAlpha(Display display, Layer layer, float alpha); + Error setLayerSidebandStream(Display display, Layer layer, + buffer_handle_t stream); + Error setLayerSourceCrop(Display display, Layer layer, + const hwc_frect_t& crop); + Error setLayerTransform(Display display, Layer layer, + int32_t transform); + Error setLayerVisibleRegion(Display display, Layer layer, + const std::vector& visible); + Error setLayerZOrder(Display display, Layer layer, uint32_t z); + +private: + void initCapabilities(); + + template + void initDispatch(T& func, hwc2_function_descriptor_t desc); + void initDispatch(); + + sp getClient(); + + static void hotplugHook(hwc2_callback_data_t callbackData, + hwc2_display_t display, int32_t connected); + static void refreshHook(hwc2_callback_data_t callbackData, + hwc2_display_t display); + static void vsyncHook(hwc2_callback_data_t callbackData, + hwc2_display_t display, int64_t timestamp); + + hwc2_device_t* mDevice; + + std::unordered_set mCapabilities; + + struct { + HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges; + HWC2_PFN_CREATE_LAYER createLayer; + HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay; + HWC2_PFN_DESTROY_LAYER destroyLayer; + HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay; + HWC2_PFN_DUMP dump; + HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig; + HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes; + HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport; + HWC2_PFN_GET_COLOR_MODES getColorModes; + HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute; + HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs; + HWC2_PFN_GET_DISPLAY_NAME getDisplayName; + HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests; + HWC2_PFN_GET_DISPLAY_TYPE getDisplayType; + HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport; + HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities; + HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount; + HWC2_PFN_GET_RELEASE_FENCES getReleaseFences; + HWC2_PFN_PRESENT_DISPLAY presentDisplay; + HWC2_PFN_REGISTER_CALLBACK registerCallback; + HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig; + HWC2_PFN_SET_CLIENT_TARGET setClientTarget; + HWC2_PFN_SET_COLOR_MODE setColorMode; + HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform; + HWC2_PFN_SET_CURSOR_POSITION setCursorPosition; + HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode; + HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer; + HWC2_PFN_SET_LAYER_COLOR setLayerColor; + HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType; + HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace; + HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame; + HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha; + HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream; + HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop; + HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage; + HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform; + HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion; + HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder; + HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer; + HWC2_PFN_SET_POWER_MODE setPowerMode; + HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled; + HWC2_PFN_VALIDATE_DISPLAY validateDisplay; + } mDispatch; + + std::mutex mClientMutex; + wp mClient; +}; + extern "C" IComposer* HIDL_FETCH_IComposer(const char* name); } // namespace implementation diff --git a/graphics/composer/2.1/default/HwcClient.cpp b/graphics/composer/2.1/default/HwcClient.cpp new file mode 100644 index 0000000000..16af94c1c4 --- /dev/null +++ b/graphics/composer/2.1/default/HwcClient.cpp @@ -0,0 +1,1126 @@ +/* + * Copyright 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. + */ + +#define LOG_TAG "HwcPassthrough" + +#include +#include +#include + +#include "Hwc.h" +#include "HwcClient.h" +#include "IComposerCommandBuffer.h" + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace implementation { + +namespace { + +class HandleImporter { +public: + HandleImporter() : mInitialized(false) {} + + bool initialize() + { + // allow only one client + if (mInitialized) { + return false; + } + + if (!openGralloc()) { + return false; + } + + mInitialized = true; + return true; + } + + void cleanup() + { + if (!mInitialized) { + return; + } + + closeGralloc(); + mInitialized = false; + } + + // In IComposer, any buffer_handle_t is owned by the caller and we need to + // make a clone for hwcomposer2. We also need to translate empty handle + // to nullptr. This function does that, in-place. + bool importBuffer(buffer_handle_t& handle) + { + if (!handle) { + return true; + } + + if (!handle->numFds && !handle->numInts) { + handle = nullptr; + return true; + } + + buffer_handle_t clone = cloneBuffer(handle); + if (!clone) { + return false; + } + + handle = clone; + return true; + } + + void freeBuffer(buffer_handle_t handle) + { + if (!handle) { + return; + } + + releaseBuffer(handle); + } + +private: + bool mInitialized; + + // Some existing gralloc drivers do not support retaining more than once, + // when we are in passthrough mode. +#ifdef BINDERIZED + bool openGralloc() + { + const hw_module_t* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + if (err) { + ALOGE("failed to get gralloc module"); + return false; + } + + uint8_t major = (module->module_api_version >> 8) & 0xff; + if (major > 1) { + ALOGE("unknown gralloc module major version %d", major); + return false; + } + + if (major == 1) { + err = gralloc1_open(module, &mDevice); + if (err) { + ALOGE("failed to open gralloc1 device"); + return false; + } + + mRetain = reinterpret_cast( + mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN)); + mRelease = reinterpret_cast( + mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE)); + if (!mRetain || !mRelease) { + ALOGE("invalid gralloc1 device"); + gralloc1_close(mDevice); + return false; + } + } else { + mModule = reinterpret_cast(module); + } + + return true; + } + + void closeGralloc() + { + if (mDevice) { + gralloc1_close(mDevice); + } + } + + buffer_handle_t cloneBuffer(buffer_handle_t handle) + { + native_handle_t* clone = native_handle_clone(handle); + if (!clone) { + ALOGE("failed to clone buffer %p", handle); + return nullptr; + } + + bool err; + if (mDevice) { + err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE); + } else { + err = (mModule->registerBuffer(mModule, clone) != 0); + } + + if (err) { + ALOGE("failed to retain/register buffer %p", clone); + native_handle_close(clone); + native_handle_delete(clone); + return nullptr; + } + + return clone; + } + + void releaseBuffer(buffer_handle_t handle) + { + if (mDevice) { + mRelease(mDevice, handle); + } else { + mModule->unregisterBuffer(mModule, handle); + native_handle_close(handle); + native_handle_delete(const_cast(handle)); + } + } + + // gralloc1 + gralloc1_device_t* mDevice; + GRALLOC1_PFN_RETAIN mRetain; + GRALLOC1_PFN_RELEASE mRelease; + + // gralloc0 + const gralloc_module_t* mModule; +#else + bool openGralloc() { return true; } + void closeGralloc() {} + buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; } + void releaseBuffer(buffer_handle_t) {} +#endif +}; + +HandleImporter sHandleImporter; + +} // anonymous namespace + +BufferClone::BufferClone() + : mHandle(nullptr) +{ +} + +BufferClone::BufferClone(BufferClone&& other) +{ + mHandle = other.mHandle; + other.mHandle = nullptr; +} + +BufferClone& BufferClone::operator=(buffer_handle_t handle) +{ + clear(); + mHandle = handle; + return *this; +} + +BufferClone::~BufferClone() +{ + clear(); +} + +void BufferClone::clear() +{ + if (mHandle) { + sHandleImporter.freeBuffer(mHandle); + } +} + +HwcClient::HwcClient(HwcHal& hal) + : mHal(hal), mReader(*this), mWriter(kWriterInitialSize) +{ + if (!sHandleImporter.initialize()) { + LOG_ALWAYS_FATAL("failed to initialize handle importer"); + } +} + +HwcClient::~HwcClient() +{ + mHal.enableCallback(false); + mHal.removeClient(); + + // no need to grab the mutex as any in-flight hwbinder call should keep + // the client alive + for (const auto& dpy : mDisplayData) { + if (!dpy.second.Layers.empty()) { + ALOGW("client destroyed with valid layers"); + } + for (const auto& ly : dpy.second.Layers) { + mHal.destroyLayer(dpy.first, ly.first); + } + + if (dpy.second.IsVirtual) { + ALOGW("client destroyed with valid virtual display"); + mHal.destroyVirtualDisplay(dpy.first); + } + } + + mDisplayData.clear(); + + sHandleImporter.cleanup(); +} + +void HwcClient::onHotplug(Display display, + IComposerCallback::Connection connected) +{ + { + std::lock_guard lock(mDisplayDataMutex); + + if (connected == IComposerCallback::Connection::CONNECTED) { + mDisplayData.emplace(display, DisplayData(false)); + } else if (connected == IComposerCallback::Connection::DISCONNECTED) { + mDisplayData.erase(display); + } + } + + mCallback->onHotplug(display, connected); +} + +void HwcClient::onRefresh(Display display) +{ + mCallback->onRefresh(display); +} + +void HwcClient::onVsync(Display display, int64_t timestamp) +{ + mCallback->onVsync(display, timestamp); +} + +Return HwcClient::registerCallback(const sp& callback) +{ + // no locking as we require this function to be called only once + mCallback = callback; + mHal.enableCallback(callback != nullptr); + + return Void(); +} + +Return HwcClient::getMaxVirtualDisplayCount() +{ + return mHal.getMaxVirtualDisplayCount(); +} + +Return HwcClient::createVirtualDisplay(uint32_t width, uint32_t height, + PixelFormat formatHint, uint32_t outputBufferSlotCount, + createVirtualDisplay_cb hidl_cb) +{ + Display display; + Error err = mHal.createVirtualDisplay(width, height, formatHint, display); + if (err == Error::NONE) { + std::lock_guard lock(mDisplayDataMutex); + + auto dpy = mDisplayData.emplace(display, DisplayData(true)).first; + dpy->second.OutputBuffers.resize(outputBufferSlotCount); + } + + hidl_cb(err, display, formatHint); + return Void(); +} + +Return HwcClient::destroyVirtualDisplay(Display display) +{ + Error err = mHal.destroyVirtualDisplay(display); + if (err == Error::NONE) { + std::lock_guard lock(mDisplayDataMutex); + + mDisplayData.erase(display); + } + + return err; +} + +Return HwcClient::createLayer(Display display, uint32_t bufferSlotCount, + createLayer_cb hidl_cb) +{ + Layer layer; + Error err = mHal.createLayer(display, layer); + if (err == Error::NONE) { + std::lock_guard lock(mDisplayDataMutex); + + auto dpy = mDisplayData.find(display); + auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first; + ly->second.Buffers.resize(bufferSlotCount); + } + + hidl_cb(err, layer); + return Void(); +} + +Return HwcClient::destroyLayer(Display display, Layer layer) +{ + Error err = mHal.destroyLayer(display, layer); + if (err == Error::NONE) { + std::lock_guard lock(mDisplayDataMutex); + + auto dpy = mDisplayData.find(display); + dpy->second.Layers.erase(layer); + } + + return err; +} + +Return HwcClient::getActiveConfig(Display display, + getActiveConfig_cb hidl_cb) +{ + Config config; + Error err = mHal.getActiveConfig(display, config); + + hidl_cb(err, config); + return Void(); +} + +Return HwcClient::getClientTargetSupport(Display display, + uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace) +{ + Error err = mHal.getClientTargetSupport(display, + width, height, format, dataspace); + return err; +} + +Return HwcClient::getColorModes(Display display, getColorModes_cb hidl_cb) +{ + hidl_vec modes; + Error err = mHal.getColorModes(display, modes); + + hidl_cb(err, modes); + return Void(); +} + +Return HwcClient::getDisplayAttribute(Display display, + Config config, Attribute attribute, + getDisplayAttribute_cb hidl_cb) +{ + int32_t value; + Error err = mHal.getDisplayAttribute(display, config, attribute, value); + + hidl_cb(err, value); + return Void(); +} + +Return HwcClient::getDisplayConfigs(Display display, + getDisplayConfigs_cb hidl_cb) +{ + hidl_vec configs; + Error err = mHal.getDisplayConfigs(display, configs); + + hidl_cb(err, configs); + return Void(); +} + +Return HwcClient::getDisplayName(Display display, + getDisplayName_cb hidl_cb) +{ + hidl_string name; + Error err = mHal.getDisplayName(display, name); + + hidl_cb(err, name); + return Void(); +} + +Return HwcClient::getDisplayType(Display display, + getDisplayType_cb hidl_cb) +{ + DisplayType type; + Error err = mHal.getDisplayType(display, type); + + hidl_cb(err, type); + return Void(); +} + +Return HwcClient::getDozeSupport(Display display, + getDozeSupport_cb hidl_cb) +{ + bool support; + Error err = mHal.getDozeSupport(display, support); + + hidl_cb(err, support); + return Void(); +} + +Return HwcClient::getHdrCapabilities(Display display, + getHdrCapabilities_cb hidl_cb) +{ + hidl_vec types; + float max_lumi = 0.0f; + float max_avg_lumi = 0.0f; + float min_lumi = 0.0f; + Error err = mHal.getHdrCapabilities(display, types, + max_lumi, max_avg_lumi, min_lumi); + + hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi); + return Void(); +} + +Return HwcClient::setClientTargetSlotCount(Display display, + uint32_t clientTargetSlotCount) +{ + std::lock_guard lock(mDisplayDataMutex); + + auto dpy = mDisplayData.find(display); + if (dpy == mDisplayData.end()) { + return Error::BAD_DISPLAY; + } + + dpy->second.ClientTargets.resize(clientTargetSlotCount); + + return Error::NONE; +} + +Return HwcClient::setActiveConfig(Display display, Config config) +{ + Error err = mHal.setActiveConfig(display, config); + return err; +} + +Return HwcClient::setColorMode(Display display, ColorMode mode) +{ + Error err = mHal.setColorMode(display, mode); + return err; +} + +Return HwcClient::setPowerMode(Display display, PowerMode mode) +{ + Error err = mHal.setPowerMode(display, mode); + return err; +} + +Return HwcClient::setVsyncEnabled(Display display, Vsync enabled) +{ + Error err = mHal.setVsyncEnabled(display, enabled); + return err; +} + +Return HwcClient::setInputCommandQueue( + const MQDescriptorSync& descriptor) +{ + std::lock_guard lock(mCommandMutex); + return mReader.setMQDescriptor(descriptor) ? + Error::NONE : Error::NO_RESOURCES; +} + +Return HwcClient::getOutputCommandQueue( + getOutputCommandQueue_cb hidl_cb) +{ + // no locking as we require this function to be called inside + // executeCommands_cb + + auto outDescriptor = mWriter.getMQDescriptor(); + if (outDescriptor) { + hidl_cb(Error::NONE, *outDescriptor); + } else { + hidl_cb(Error::NO_RESOURCES, MQDescriptorSync(0, nullptr, 0)); + } + + return Void(); +} + +Return HwcClient::executeCommands(uint32_t inLength, + const hidl_vec& inHandles, + executeCommands_cb hidl_cb) +{ + std::lock_guard lock(mCommandMutex); + + bool outChanged = false; + uint32_t outLength = 0; + hidl_vec outHandles; + + if (!mReader.readQueue(inLength, inHandles)) { + hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles); + return Void(); + } + + Error err = mReader.parse(); + if (err == Error::NONE && + !mWriter.writeQueue(outChanged, outLength, outHandles)) { + err = Error::NO_RESOURCES; + } + + hidl_cb(err, outChanged, outLength, outHandles); + + mReader.reset(); + mWriter.reset(); + + return Void(); +} + +HwcClient::CommandReader::CommandReader(HwcClient& client) + : mClient(client), mHal(client.mHal), mWriter(client.mWriter) +{ +} + +Error HwcClient::CommandReader::parse() +{ + IComposerClient::Command command; + uint16_t length; + + while (!isEmpty()) { + if (!beginCommand(command, length)) { + break; + } + + bool parsed = false; + switch (command) { + case IComposerClient::Command::SELECT_DISPLAY: + parsed = parseSelectDisplay(length); + break; + case IComposerClient::Command::SELECT_LAYER: + parsed = parseSelectLayer(length); + break; + case IComposerClient::Command::SET_COLOR_TRANSFORM: + parsed = parseSetColorTransform(length); + break; + case IComposerClient::Command::SET_CLIENT_TARGET: + parsed = parseSetClientTarget(length); + break; + case IComposerClient::Command::SET_OUTPUT_BUFFER: + parsed = parseSetOutputBuffer(length); + break; + case IComposerClient::Command::VALIDATE_DISPLAY: + parsed = parseValidateDisplay(length); + break; + case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES: + parsed = parseAcceptDisplayChanges(length); + break; + case IComposerClient::Command::PRESENT_DISPLAY: + parsed = parsePresentDisplay(length); + break; + case IComposerClient::Command::SET_LAYER_CURSOR_POSITION: + parsed = parseSetLayerCursorPosition(length); + break; + case IComposerClient::Command::SET_LAYER_BUFFER: + parsed = parseSetLayerBuffer(length); + break; + case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE: + parsed = parseSetLayerSurfaceDamage(length); + break; + case IComposerClient::Command::SET_LAYER_BLEND_MODE: + parsed = parseSetLayerBlendMode(length); + break; + case IComposerClient::Command::SET_LAYER_COLOR: + parsed = parseSetLayerColor(length); + break; + case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE: + parsed = parseSetLayerCompositionType(length); + break; + case IComposerClient::Command::SET_LAYER_DATASPACE: + parsed = parseSetLayerDataspace(length); + break; + case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME: + parsed = parseSetLayerDisplayFrame(length); + break; + case IComposerClient::Command::SET_LAYER_PLANE_ALPHA: + parsed = parseSetLayerPlaneAlpha(length); + break; + case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM: + parsed = parseSetLayerSidebandStream(length); + break; + case IComposerClient::Command::SET_LAYER_SOURCE_CROP: + parsed = parseSetLayerSourceCrop(length); + break; + case IComposerClient::Command::SET_LAYER_TRANSFORM: + parsed = parseSetLayerTransform(length); + break; + case IComposerClient::Command::SET_LAYER_VISIBLE_REGION: + parsed = parseSetLayerVisibleRegion(length); + break; + case IComposerClient::Command::SET_LAYER_Z_ORDER: + parsed = parseSetLayerZOrder(length); + break; + default: + parsed = false; + break; + } + + endCommand(); + + if (!parsed) { + ALOGE("failed to parse command 0x%x, length %" PRIu16, + command, length); + break; + } + } + + return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER; +} + +bool HwcClient::CommandReader::parseSelectDisplay(uint16_t length) +{ + if (length != CommandWriter::kSelectDisplayLength) { + return false; + } + + mDisplay = read64(); + mWriter.selectDisplay(mDisplay); + + return true; +} + +bool HwcClient::CommandReader::parseSelectLayer(uint16_t length) +{ + if (length != CommandWriter::kSelectLayerLength) { + return false; + } + + mLayer = read64(); + + return true; +} + +bool HwcClient::CommandReader::parseSetColorTransform(uint16_t length) +{ + if (length != CommandWriter::kSetColorTransformLength) { + return false; + } + + float matrix[16]; + for (int i = 0; i < 16; i++) { + matrix[i] = readFloat(); + } + auto transform = readSigned(); + + auto err = mHal.setColorTransform(mDisplay, matrix, transform); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetClientTarget(uint16_t length) +{ + // 4 parameters followed by N rectangles + if ((length - 4) % 4 != 0) { + return false; + } + + bool useCache; + auto slot = read(); + auto clientTarget = readHandle(useCache); + auto fence = readFence(); + auto dataspace = readSigned(); + auto damage = readRegion((length - 4) / 4); + + auto err = lookupBuffer(BufferCache::CLIENT_TARGETS, + slot, useCache, clientTarget); + if (err == Error::NONE) { + err = mHal.setClientTarget(mDisplay, clientTarget, fence, + dataspace, damage); + } + if (err != Error::NONE) { + close(fence); + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetOutputBuffer(uint16_t length) +{ + if (length != CommandWriter::kSetOutputBufferLength) { + return false; + } + + bool useCache; + auto slot = read(); + auto outputBuffer = readHandle(useCache); + auto fence = readFence(); + + auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS, + slot, useCache, outputBuffer); + if (err == Error::NONE) { + err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence); + } + if (err != Error::NONE) { + close(fence); + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseValidateDisplay(uint16_t length) +{ + if (length != CommandWriter::kValidateDisplayLength) { + return false; + } + + std::vector changedLayers; + std::vector compositionTypes; + uint32_t displayRequestMask; + std::vector requestedLayers; + std::vector requestMasks; + + auto err = mHal.validateDisplay(mDisplay, changedLayers, compositionTypes, + displayRequestMask, requestedLayers, requestMasks); + if (err == Error::NONE) { + mWriter.setChangedCompositionTypes(changedLayers, + compositionTypes); + mWriter.setDisplayRequests(displayRequestMask, + requestedLayers, requestMasks); + } else { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseAcceptDisplayChanges(uint16_t length) +{ + if (length != CommandWriter::kAcceptDisplayChangesLength) { + return false; + } + + auto err = mHal.acceptDisplayChanges(mDisplay); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parsePresentDisplay(uint16_t length) +{ + if (length != CommandWriter::kPresentDisplayLength) { + return false; + } + + int presentFence; + std::vector layers; + std::vector fences; + auto err = mHal.presentDisplay(mDisplay, presentFence, layers, fences); + if (err == Error::NONE) { + mWriter.setPresentFence(presentFence); + mWriter.setReleaseFences(layers, fences); + } else { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerCursorPosition(uint16_t length) +{ + if (length != CommandWriter::kSetLayerCursorPositionLength) { + return false; + } + + auto err = mHal.setLayerCursorPosition(mDisplay, mLayer, + readSigned(), readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerBuffer(uint16_t length) +{ + if (length != CommandWriter::kSetLayerBufferLength) { + return false; + } + + bool useCache; + auto slot = read(); + auto buffer = readHandle(useCache); + auto fence = readFence(); + + auto err = lookupBuffer(BufferCache::LAYER_BUFFERS, + slot, useCache, buffer); + if (err == Error::NONE) { + err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence); + } + if (err != Error::NONE) { + close(fence); + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length) +{ + // N rectangles + if (length % 4 != 0) { + return false; + } + + auto damage = readRegion(length / 4); + auto err = mHal.setLayerSurfaceDamage(mDisplay, mLayer, damage); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerBlendMode(uint16_t length) +{ + if (length != CommandWriter::kSetLayerBlendModeLength) { + return false; + } + + auto err = mHal.setLayerBlendMode(mDisplay, mLayer, readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerColor(uint16_t length) +{ + if (length != CommandWriter::kSetLayerColorLength) { + return false; + } + + auto err = mHal.setLayerColor(mDisplay, mLayer, readColor()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerCompositionType(uint16_t length) +{ + if (length != CommandWriter::kSetLayerCompositionTypeLength) { + return false; + } + + auto err = mHal.setLayerCompositionType(mDisplay, mLayer, readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerDataspace(uint16_t length) +{ + if (length != CommandWriter::kSetLayerDataspaceLength) { + return false; + } + + auto err = mHal.setLayerDataspace(mDisplay, mLayer, readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length) +{ + if (length != CommandWriter::kSetLayerDisplayFrameLength) { + return false; + } + + auto err = mHal.setLayerDisplayFrame(mDisplay, mLayer, readRect()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length) +{ + if (length != CommandWriter::kSetLayerPlaneAlphaLength) { + return false; + } + + auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, read()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerSidebandStream(uint16_t length) +{ + if (length != CommandWriter::kSetLayerSidebandStreamLength) { + return false; + } + + auto stream = readHandle(); + + auto err = lookupLayerSidebandStream(stream); + if (err == Error::NONE) { + err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream); + } + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerSourceCrop(uint16_t length) +{ + if (length != CommandWriter::kSetLayerSourceCropLength) { + return false; + } + + auto err = mHal.setLayerSourceCrop(mDisplay, mLayer, readFRect()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerTransform(uint16_t length) +{ + if (length != CommandWriter::kSetLayerTransformLength) { + return false; + } + + auto err = mHal.setLayerTransform(mDisplay, mLayer, readSigned()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length) +{ + // N rectangles + if (length % 4 != 0) { + return false; + } + + auto region = readRegion(length / 4); + auto err = mHal.setLayerVisibleRegion(mDisplay, mLayer, region); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +bool HwcClient::CommandReader::parseSetLayerZOrder(uint16_t length) +{ + if (length != CommandWriter::kSetLayerZOrderLength) { + return false; + } + + auto err = mHal.setLayerZOrder(mDisplay, mLayer, read()); + if (err != Error::NONE) { + mWriter.setError(getCommandLoc(), err); + } + + return true; +} + +hwc_rect_t HwcClient::CommandReader::readRect() +{ + return hwc_rect_t{ + readSigned(), + readSigned(), + readSigned(), + readSigned(), + }; +} + +std::vector HwcClient::CommandReader::readRegion(size_t count) +{ + std::vector region; + region.reserve(count); + while (count > 0) { + region.emplace_back(readRect()); + count--; + } + + return region; +} + +hwc_frect_t HwcClient::CommandReader::readFRect() +{ + return hwc_frect_t{ + readFloat(), + readFloat(), + readFloat(), + readFloat(), + }; +} + +Error HwcClient::CommandReader::lookupBuffer(BufferCache cache, uint32_t slot, + bool useCache, buffer_handle_t& handle) +{ + std::lock_guard lock(mClient.mDisplayDataMutex); + + auto dpy = mClient.mDisplayData.find(mDisplay); + if (dpy == mClient.mDisplayData.end()) { + return Error::BAD_DISPLAY; + } + + BufferClone* clone = nullptr; + switch (cache) { + case BufferCache::CLIENT_TARGETS: + if (slot < dpy->second.ClientTargets.size()) { + clone = &dpy->second.ClientTargets[slot]; + } + break; + case BufferCache::OUTPUT_BUFFERS: + if (slot < dpy->second.OutputBuffers.size()) { + clone = &dpy->second.OutputBuffers[slot]; + } + break; + case BufferCache::LAYER_BUFFERS: + { + auto ly = dpy->second.Layers.find(mLayer); + if (ly == dpy->second.Layers.end()) { + return Error::BAD_LAYER; + } + if (slot < ly->second.Buffers.size()) { + clone = &ly->second.Buffers[slot]; + } + } + break; + case BufferCache::LAYER_SIDEBAND_STREAMS: + { + auto ly = dpy->second.Layers.find(mLayer); + if (ly == dpy->second.Layers.end()) { + return Error::BAD_LAYER; + } + if (slot == 0) { + clone = &ly->second.SidebandStream; + } + } + break; + default: + break; + } + + if (!clone) { + ALOGW("invalid buffer slot"); + return Error::BAD_PARAMETER; + } + + // use or update cache + if (useCache) { + handle = *clone; + } else { + if (!sHandleImporter.importBuffer(handle)) { + return Error::NO_RESOURCES; + } + + *clone = handle; + } + + return Error::NONE; +} + +} // namespace implementation +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/composer/2.1/default/HwcClient.h b/graphics/composer/2.1/default/HwcClient.h new file mode 100644 index 0000000000..a9bc4cd338 --- /dev/null +++ b/graphics/composer/2.1/default/HwcClient.h @@ -0,0 +1,202 @@ +/* + * Copyright 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 ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_CLIENT_H +#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_CLIENT_H + +#include +#include +#include + +#include "Hwc.h" +#include "IComposerCommandBuffer.h" + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace implementation { + +class BufferClone { +public: + BufferClone(); + BufferClone(BufferClone&& other); + + BufferClone(const BufferClone& other) = delete; + BufferClone& operator=(const BufferClone& other) = delete; + + BufferClone& operator=(buffer_handle_t handle); + ~BufferClone(); + + operator buffer_handle_t() const { return mHandle; } + +private: + void clear(); + + buffer_handle_t mHandle; +}; + +class HwcClient : public IComposerClient { +public: + HwcClient(HwcHal& hal); + virtual ~HwcClient(); + + void onHotplug(Display display, IComposerCallback::Connection connected); + void onRefresh(Display display); + void onVsync(Display display, int64_t timestamp); + + // IComposerClient interface + Return registerCallback( + const sp& callback) override; + Return getMaxVirtualDisplayCount() override; + Return createVirtualDisplay(uint32_t width, uint32_t height, + PixelFormat formatHint, uint32_t outputBufferSlotCount, + createVirtualDisplay_cb hidl_cb) override; + Return destroyVirtualDisplay(Display display) override; + Return createLayer(Display display, uint32_t bufferSlotCount, + createLayer_cb hidl_cb) override; + Return destroyLayer(Display display, Layer layer) override; + Return getActiveConfig(Display display, + getActiveConfig_cb hidl_cb) override; + Return getClientTargetSupport(Display display, + uint32_t width, uint32_t height, + PixelFormat format, Dataspace dataspace) override; + Return getColorModes(Display display, + getColorModes_cb hidl_cb) override; + Return getDisplayAttribute(Display display, + Config config, Attribute attribute, + getDisplayAttribute_cb hidl_cb) override; + Return getDisplayConfigs(Display display, + getDisplayConfigs_cb hidl_cb) override; + Return getDisplayName(Display display, + getDisplayName_cb hidl_cb) override; + Return getDisplayType(Display display, + getDisplayType_cb hidl_cb) override; + Return getDozeSupport(Display display, + getDozeSupport_cb hidl_cb) override; + Return getHdrCapabilities(Display display, + getHdrCapabilities_cb hidl_cb) override; + Return setActiveConfig(Display display, Config config) override; + Return setColorMode(Display display, ColorMode mode) override; + Return setPowerMode(Display display, PowerMode mode) override; + Return setVsyncEnabled(Display display, Vsync enabled) override; + Return setClientTargetSlotCount(Display display, + uint32_t clientTargetSlotCount) override; + Return setInputCommandQueue( + const MQDescriptorSync& descriptor) override; + Return getOutputCommandQueue( + getOutputCommandQueue_cb hidl_cb) override; + Return executeCommands(uint32_t inLength, + const hidl_vec& inHandles, + executeCommands_cb hidl_cb) override; + +private: + struct LayerBuffers { + std::vector Buffers; + BufferClone SidebandStream; + }; + + struct DisplayData { + bool IsVirtual; + + std::vector ClientTargets; + std::vector OutputBuffers; + + std::unordered_map Layers; + + DisplayData(bool isVirtual) : IsVirtual(isVirtual) {} + }; + + class CommandReader : public CommandReaderBase { + public: + CommandReader(HwcClient& client); + Error parse(); + + private: + bool parseSelectDisplay(uint16_t length); + bool parseSelectLayer(uint16_t length); + bool parseSetColorTransform(uint16_t length); + bool parseSetClientTarget(uint16_t length); + bool parseSetOutputBuffer(uint16_t length); + bool parseValidateDisplay(uint16_t length); + bool parseAcceptDisplayChanges(uint16_t length); + bool parsePresentDisplay(uint16_t length); + bool parseSetLayerCursorPosition(uint16_t length); + bool parseSetLayerBuffer(uint16_t length); + bool parseSetLayerSurfaceDamage(uint16_t length); + bool parseSetLayerBlendMode(uint16_t length); + bool parseSetLayerColor(uint16_t length); + bool parseSetLayerCompositionType(uint16_t length); + bool parseSetLayerDataspace(uint16_t length); + bool parseSetLayerDisplayFrame(uint16_t length); + bool parseSetLayerPlaneAlpha(uint16_t length); + bool parseSetLayerSidebandStream(uint16_t length); + bool parseSetLayerSourceCrop(uint16_t length); + bool parseSetLayerTransform(uint16_t length); + bool parseSetLayerVisibleRegion(uint16_t length); + bool parseSetLayerZOrder(uint16_t length); + + hwc_rect_t readRect(); + std::vector readRegion(size_t count); + hwc_frect_t readFRect(); + + enum class BufferCache { + CLIENT_TARGETS, + OUTPUT_BUFFERS, + LAYER_BUFFERS, + LAYER_SIDEBAND_STREAMS, + }; + Error lookupBuffer(BufferCache cache, uint32_t slot, + bool useCache, buffer_handle_t& handle); + + Error lookupLayerSidebandStream(buffer_handle_t& handle) + { + return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS, + 0, false, handle); + } + + HwcClient& mClient; + HwcHal& mHal; + CommandWriter& mWriter; + + Display mDisplay; + Layer mLayer; + }; + + HwcHal& mHal; + + // 64KiB minus a small space for metadata such as read/write pointers + static constexpr size_t kWriterInitialSize = + 64 * 1024 / sizeof(uint32_t) - 16; + std::mutex mCommandMutex; + CommandReader mReader; + CommandWriter mWriter; + + sp mCallback; + + std::mutex mDisplayDataMutex; + std::unordered_map mDisplayData; +}; + +} // namespace implementation +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_CLIENT_H diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/default/IComposerCommandBuffer.h new file mode 100644 index 0000000000..030db887b4 --- /dev/null +++ b/graphics/composer/2.1/default/IComposerCommandBuffer.h @@ -0,0 +1,848 @@ +/* + * Copyright 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 ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H +#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H + +#ifndef LOG_TAG +#warn "IComposerCommandBuffer.h included without LOG_TAG" +#endif + +#undef LOG_NDEBUG +#define LOG_NDEBUG 0 + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { + +using android::hardware::graphics::common::V1_0::ColorTransform; +using android::hardware::graphics::common::V1_0::Dataspace; +using android::hardware::graphics::common::V1_0::Transform; +using android::hardware::MessageQueue; + +using CommandQueueType = MessageQueue; + +// This class helps build a command queue. Note that all sizes/lengths are in +// units of uint32_t's. +class CommandWriter { +public: + CommandWriter(uint32_t initialMaxSize) + : mDataMaxSize(initialMaxSize) + { + mData = std::make_unique(mDataMaxSize); + reset(); + } + + ~CommandWriter() + { + reset(); + } + + void reset() + { + mDataWritten = 0; + mCommandEnd = 0; + + // handles in mDataHandles are owned by the caller + mDataHandles.clear(); + + // handles in mTemporaryHandles are owned by the writer + for (auto handle : mTemporaryHandles) { + native_handle_close(handle); + native_handle_delete(handle); + } + mTemporaryHandles.clear(); + } + + IComposerClient::Command getCommand(uint32_t offset) + { + uint32_t val = (offset < mDataWritten) ? mData[offset] : 0; + return static_cast(val & + static_cast(IComposerClient::Command::OPCODE_MASK)); + } + + bool writeQueue(bool& queueChanged, uint32_t& commandLength, + hidl_vec& commandHandles) + { + // write data to queue, optionally resizing it + if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) { + if (!mQueue->write(mData.get(), mDataWritten)) { + ALOGE("failed to write commands to message queue"); + return false; + } + + queueChanged = false; + } else { + auto newQueue = std::make_unique(mDataMaxSize); + if (!newQueue->isValid() || + !newQueue->write(mData.get(), mDataWritten)) { + ALOGE("failed to prepare a new message queue "); + return false; + } + + mQueue = std::move(newQueue); + queueChanged = true; + } + + commandLength = mDataWritten; + commandHandles.setToExternal( + const_cast(mDataHandles.data()), + mDataHandles.size()); + + return true; + } + + const MQDescriptorSync* getMQDescriptor() const + { + return (mQueue) ? mQueue->getDesc() : nullptr; + } + + static constexpr uint16_t kSelectDisplayLength = 2; + void selectDisplay(Display display) + { + beginCommand(IComposerClient::Command::SELECT_DISPLAY, + kSelectDisplayLength); + write64(display); + endCommand(); + } + + static constexpr uint16_t kSelectLayerLength = 2; + void selectLayer(Layer layer) + { + beginCommand(IComposerClient::Command::SELECT_LAYER, + kSelectLayerLength); + write64(layer); + endCommand(); + } + + static constexpr uint16_t kSetErrorLength = 2; + void setError(uint32_t location, Error error) + { + beginCommand(IComposerClient::Command::SET_ERROR, kSetErrorLength); + write(location); + writeSigned(static_cast(error)); + endCommand(); + } + + void setChangedCompositionTypes(const std::vector& layers, + const std::vector& types) + { + size_t totalLayers = std::min(layers.size(), types.size()); + size_t currentLayer = 0; + + while (currentLayer < totalLayers) { + size_t count = std::min(totalLayers - currentLayer, + static_cast(kMaxLength) / 3); + + beginCommand( + IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES, + count * 3); + for (size_t i = 0; i < count; i++) { + write64(layers[currentLayer + i]); + writeSigned(static_cast(types[currentLayer + i])); + } + endCommand(); + + currentLayer += count; + } + } + + void setDisplayRequests(uint32_t displayRequestMask, + const std::vector& layers, + const std::vector& layerRequestMasks) + { + size_t totalLayers = std::min(layers.size(), + layerRequestMasks.size()); + size_t currentLayer = 0; + + while (currentLayer < totalLayers) { + size_t count = std::min(totalLayers - currentLayer, + static_cast(kMaxLength - 1) / 3); + + beginCommand(IComposerClient::Command::SET_DISPLAY_REQUESTS, + 1 + count * 3); + write(displayRequestMask); + for (size_t i = 0; i < count; i++) { + write64(layers[currentLayer + i]); + write(static_cast(layerRequestMasks[currentLayer + i])); + } + endCommand(); + + currentLayer += count; + } + } + + static constexpr uint16_t kSetPresentFenceLength = 1; + void setPresentFence(int presentFence) + { + beginCommand(IComposerClient::Command::SET_PRESENT_FENCE, + kSetPresentFenceLength); + writeFence(presentFence); + endCommand(); + } + + void setReleaseFences(const std::vector& layers, + const std::vector& releaseFences) + { + size_t totalLayers = std::min(layers.size(), releaseFences.size()); + size_t currentLayer = 0; + + while (currentLayer < totalLayers) { + size_t count = std::min(totalLayers - currentLayer, + static_cast(kMaxLength) / 3); + + beginCommand(IComposerClient::Command::SET_RELEASE_FENCES, + count * 3); + for (size_t i = 0; i < count; i++) { + write64(layers[currentLayer + i]); + writeFence(releaseFences[currentLayer + i]); + } + endCommand(); + + currentLayer += count; + } + } + + static constexpr uint16_t kSetColorTransformLength = 17; + void setColorTransform(const float* matrix, ColorTransform hint) + { + beginCommand(IComposerClient::Command::SET_COLOR_TRANSFORM, + kSetColorTransformLength); + for (int i = 0; i < 16; i++) { + writeFloat(matrix[i]); + } + writeSigned(static_cast(hint)); + endCommand(); + } + + void setClientTarget(uint32_t slot, const native_handle_t* target, + int acquireFence, Dataspace dataspace, + const std::vector& damage) + { + bool doWrite = (damage.size() <= (kMaxLength - 4) / 4); + size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0); + + beginCommand(IComposerClient::Command::SET_CLIENT_TARGET, length); + write(slot); + writeHandle(target, true); + writeFence(acquireFence); + writeSigned(static_cast(dataspace)); + // When there are too many rectangles in the damage region and doWrite + // is false, we write no rectangle at all which means the entire + // client target is damaged. + if (doWrite) { + writeRegion(damage); + } + endCommand(); + } + + static constexpr uint16_t kSetOutputBufferLength = 3; + void setOutputBuffer(uint32_t slot, const native_handle_t* buffer, + int releaseFence) + { + beginCommand(IComposerClient::Command::SET_OUTPUT_BUFFER, + kSetOutputBufferLength); + write(slot); + writeHandle(buffer, true); + writeFence(releaseFence); + endCommand(); + } + + static constexpr uint16_t kValidateDisplayLength = 0; + void validateDisplay() + { + beginCommand(IComposerClient::Command::VALIDATE_DISPLAY, + kValidateDisplayLength); + endCommand(); + } + + static constexpr uint16_t kAcceptDisplayChangesLength = 0; + void acceptDisplayChanges() + { + beginCommand(IComposerClient::Command::ACCEPT_DISPLAY_CHANGES, + kAcceptDisplayChangesLength); + endCommand(); + } + + static constexpr uint16_t kPresentDisplayLength = 0; + void presentDisplay() + { + beginCommand(IComposerClient::Command::PRESENT_DISPLAY, + kPresentDisplayLength); + endCommand(); + } + + static constexpr uint16_t kSetLayerCursorPositionLength = 2; + void setLayerCursorPosition(int32_t x, int32_t y) + { + beginCommand(IComposerClient::Command::SET_LAYER_CURSOR_POSITION, + kSetLayerCursorPositionLength); + writeSigned(x); + writeSigned(y); + endCommand(); + } + + static constexpr uint16_t kSetLayerBufferLength = 3; + void setLayerBuffer(uint32_t slot, const native_handle_t* buffer, + int acquireFence) + { + beginCommand(IComposerClient::Command::SET_LAYER_BUFFER, + kSetLayerBufferLength); + write(slot); + writeHandle(buffer, true); + writeFence(acquireFence); + endCommand(); + } + + void setLayerSurfaceDamage( + const std::vector& damage) + { + bool doWrite = (damage.size() <= kMaxLength / 4); + size_t length = (doWrite) ? damage.size() * 4 : 0; + + beginCommand(IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE, + length); + // When there are too many rectangles in the damage region and doWrite + // is false, we write no rectangle at all which means the entire + // layer is damaged. + if (doWrite) { + writeRegion(damage); + } + endCommand(); + } + + static constexpr uint16_t kSetLayerBlendModeLength = 1; + void setLayerBlendMode(IComposerClient::BlendMode mode) + { + beginCommand(IComposerClient::Command::SET_LAYER_BLEND_MODE, + kSetLayerBlendModeLength); + writeSigned(static_cast(mode)); + endCommand(); + } + + static constexpr uint16_t kSetLayerColorLength = 1; + void setLayerColor(IComposerClient::Color color) + { + beginCommand(IComposerClient::Command::SET_LAYER_COLOR, + kSetLayerColorLength); + writeColor(color); + endCommand(); + } + + static constexpr uint16_t kSetLayerCompositionTypeLength = 1; + void setLayerCompositionType(IComposerClient::Composition type) + { + beginCommand(IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE, + kSetLayerCompositionTypeLength); + writeSigned(static_cast(type)); + endCommand(); + } + + static constexpr uint16_t kSetLayerDataspaceLength = 1; + void setLayerDataspace(Dataspace dataspace) + { + beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE, + kSetLayerDataspaceLength); + writeSigned(static_cast(dataspace)); + endCommand(); + } + + static constexpr uint16_t kSetLayerDisplayFrameLength = 4; + void setLayerDisplayFrame(const IComposerClient::Rect& frame) + { + beginCommand(IComposerClient::Command::SET_LAYER_DISPLAY_FRAME, + kSetLayerDisplayFrameLength); + writeRect(frame); + endCommand(); + } + + static constexpr uint16_t kSetLayerPlaneAlphaLength = 1; + void setLayerPlaneAlpha(float alpha) + { + beginCommand(IComposerClient::Command::SET_LAYER_PLANE_ALPHA, + kSetLayerPlaneAlphaLength); + writeFloat(alpha); + endCommand(); + } + + static constexpr uint16_t kSetLayerSidebandStreamLength = 1; + void setLayerSidebandStream(const native_handle_t* stream) + { + beginCommand(IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM, + kSetLayerSidebandStreamLength); + writeHandle(stream); + endCommand(); + } + + static constexpr uint16_t kSetLayerSourceCropLength = 4; + void setLayerSourceCrop(const IComposerClient::FRect& crop) + { + beginCommand(IComposerClient::Command::SET_LAYER_SOURCE_CROP, + kSetLayerSourceCropLength); + writeFRect(crop); + endCommand(); + } + + static constexpr uint16_t kSetLayerTransformLength = 1; + void setLayerTransform(Transform transform) + { + beginCommand(IComposerClient::Command::SET_LAYER_TRANSFORM, + kSetLayerTransformLength); + writeSigned(static_cast(transform)); + endCommand(); + } + + void setLayerVisibleRegion( + const std::vector& visible) + { + bool doWrite = (visible.size() <= kMaxLength / 4); + size_t length = (doWrite) ? visible.size() * 4 : 0; + + beginCommand(IComposerClient::Command::SET_LAYER_VISIBLE_REGION, + length); + // When there are too many rectangles in the visible region and + // doWrite is false, we write no rectangle at all which means the + // entire layer is visible. + if (doWrite) { + writeRegion(visible); + } + endCommand(); + } + + static constexpr uint16_t kSetLayerZOrderLength = 1; + void setLayerZOrder(uint32_t z) + { + beginCommand(IComposerClient::Command::SET_LAYER_Z_ORDER, + kSetLayerZOrderLength); + write(z); + endCommand(); + } + +protected: + void beginCommand(IComposerClient::Command command, uint16_t length) + { + if (mCommandEnd) { + LOG_FATAL("endCommand was not called before command 0x%x", + command); + } + + growData(1 + length); + write(static_cast(command) | length); + + mCommandEnd = mDataWritten + length; + } + + void endCommand() + { + if (!mCommandEnd) { + LOG_FATAL("beginCommand was not called"); + } else if (mDataWritten > mCommandEnd) { + LOG_FATAL("too much data written"); + mDataWritten = mCommandEnd; + } else if (mDataWritten < mCommandEnd) { + LOG_FATAL("too little data written"); + while (mDataWritten < mCommandEnd) { + write(0); + } + } + + mCommandEnd = 0; + } + + void write(uint32_t val) + { + mData[mDataWritten++] = val; + } + + void writeSigned(int32_t val) + { + memcpy(&mData[mDataWritten++], &val, sizeof(val)); + } + + void writeFloat(float val) + { + memcpy(&mData[mDataWritten++], &val, sizeof(val)); + } + + void write64(uint64_t val) + { + uint32_t lo = static_cast(val & 0xffffffff); + uint32_t hi = static_cast(val >> 32); + write(lo); + write(hi); + } + + void writeRect(const IComposerClient::Rect& rect) + { + writeSigned(rect.left); + writeSigned(rect.top); + writeSigned(rect.right); + writeSigned(rect.bottom); + } + + void writeRegion(const std::vector& region) + { + for (const auto& rect : region) { + writeRect(rect); + } + } + + void writeFRect(const IComposerClient::FRect& rect) + { + writeFloat(rect.left); + writeFloat(rect.top); + writeFloat(rect.right); + writeFloat(rect.bottom); + } + + void writeColor(const IComposerClient::Color& color) + { + write((color.r << 0) | + (color.g << 8) | + (color.b << 16) | + (color.a << 24)); + } + + // ownership of handle is not transferred + void writeHandle(const native_handle_t* handle, bool useCache) + { + if (!handle) { + writeSigned(static_cast((useCache) ? + IComposerClient::HandleIndex::CACHED : + IComposerClient::HandleIndex::EMPTY)); + return; + } + + mDataHandles.push_back(handle); + writeSigned(mDataHandles.size() - 1); + } + + void writeHandle(const native_handle_t* handle) + { + writeHandle(handle, false); + } + + // ownership of fence is transferred + void writeFence(int fence) + { + native_handle_t* handle = nullptr; + if (fence >= 0) { + handle = getTemporaryHandle(1, 0); + if (handle) { + handle->data[0] = fence; + } else { + ALOGW("failed to get temporary handle for fence %d", fence); + sync_wait(fence, -1); + close(fence); + } + } + + writeHandle(handle); + } + + native_handle_t* getTemporaryHandle(int numFds, int numInts) + { + native_handle_t* handle = native_handle_create(numFds, numInts); + if (handle) { + mTemporaryHandles.push_back(handle); + } + return handle; + } + + static constexpr uint16_t kMaxLength = + std::numeric_limits::max(); + +private: + void growData(uint32_t grow) + { + uint32_t newWritten = mDataWritten + grow; + if (newWritten < mDataWritten) { + LOG_ALWAYS_FATAL("buffer overflowed; data written %" PRIu32 + ", growing by %" PRIu32, mDataWritten, grow); + } + + if (newWritten <= mDataMaxSize) { + return; + } + + uint32_t newMaxSize = mDataMaxSize << 1; + if (newMaxSize < newWritten) { + newMaxSize = newWritten; + } + + auto newData = std::make_unique(newMaxSize); + std::copy_n(mData.get(), mDataWritten, newData.get()); + mDataMaxSize = newMaxSize; + mData = std::move(newData); + } + + uint32_t mDataMaxSize; + std::unique_ptr mData; + + uint32_t mDataWritten; + // end offset of the current command + uint32_t mCommandEnd; + + std::vector mDataHandles; + std::vector mTemporaryHandles; + + std::unique_ptr mQueue; +}; + +// This class helps parse a command queue. Note that all sizes/lengths are in +// units of uint32_t's. +class CommandReaderBase { +public: + CommandReaderBase() : mDataMaxSize(0) + { + reset(); + } + + bool setMQDescriptor(const MQDescriptorSync& descriptor) + { + mQueue = std::make_unique(descriptor, false); + if (mQueue->isValid()) { + return true; + } else { + mQueue = nullptr; + return false; + } + } + + bool readQueue(uint32_t commandLength, + const hidl_vec& commandHandles) + { + if (!mQueue) { + return false; + } + + auto quantumCount = mQueue->getQuantumCount(); + if (mDataMaxSize < quantumCount) { + mDataMaxSize = quantumCount; + mData = std::make_unique(mDataMaxSize); + } + + if (commandLength > mDataMaxSize || + !mQueue->read(mData.get(), commandLength)) { + ALOGE("failed to read commands from message queue"); + return false; + } + + mDataSize = commandLength; + mDataRead = 0; + mCommandBegin = 0; + mCommandEnd = 0; + mDataHandles.setToExternal( + const_cast(commandHandles.data()), + commandHandles.size()); + + return true; + } + + void reset() + { + mDataSize = 0; + mDataRead = 0; + mCommandBegin = 0; + mCommandEnd = 0; + mDataHandles.setToExternal(nullptr, 0); + } + +protected: + bool isEmpty() const + { + return (mDataRead >= mDataSize); + } + + bool beginCommand(IComposerClient::Command& command, uint16_t& length) + { + if (mCommandEnd) { + LOG_FATAL("endCommand was not called before command 0x%x", + command); + } + + constexpr uint32_t opcode_mask = + static_cast(IComposerClient::Command::OPCODE_MASK); + constexpr uint32_t length_mask = + static_cast(IComposerClient::Command::LENGTH_MASK); + + uint32_t val = read(); + command = static_cast(val & opcode_mask); + length = static_cast(val & length_mask); + + if (mDataRead + length > mDataSize) { + ALOGE("command 0x%x has invalid command length %" PRIu16, + command, length); + // undo the read() above + mDataRead--; + return false; + } + + mCommandEnd = mDataRead + length; + + return true; + } + + void endCommand() + { + if (!mCommandEnd) { + LOG_FATAL("beginCommand was not called"); + } else if (mDataRead > mCommandEnd) { + LOG_FATAL("too much data read"); + mDataRead = mCommandEnd; + } else if (mDataRead < mCommandEnd) { + LOG_FATAL("too little data read"); + mDataRead = mCommandEnd; + } + + mCommandBegin = mCommandEnd; + mCommandEnd = 0; + } + + uint32_t getCommandLoc() const + { + return mCommandBegin; + } + + uint32_t read() + { + return mData[mDataRead++]; + } + + int32_t readSigned() + { + int32_t val; + memcpy(&val, &mData[mDataRead++], sizeof(val)); + return val; + } + + float readFloat() + { + float val; + memcpy(&val, &mData[mDataRead++], sizeof(val)); + return val; + } + + uint64_t read64() + { + uint32_t lo = read(); + uint32_t hi = read(); + return (static_cast(hi) << 32) | lo; + } + + IComposerClient::Color readColor() + { + uint32_t val = read(); + return IComposerClient::Color{ + static_cast((val >> 0) & 0xff), + static_cast((val >> 8) & 0xff), + static_cast((val >> 16) & 0xff), + static_cast((val >> 24) & 0xff), + }; + } + + // ownership of handle is not transferred + const native_handle_t* readHandle(bool& useCache) + { + const native_handle_t* handle = nullptr; + + int32_t index = readSigned(); + switch (index) { + case static_cast(IComposerClient::HandleIndex::EMPTY): + useCache = false; + break; + case static_cast(IComposerClient::HandleIndex::CACHED): + useCache = true; + break; + default: + if (static_cast(index) < mDataHandles.size()) { + handle = mDataHandles[index].getNativeHandle(); + } else { + ALOGE("invalid handle index %zu", static_cast(index)); + } + useCache = false; + break; + } + + return handle; + } + + const native_handle_t* readHandle() + { + bool useCache; + return readHandle(useCache); + } + + // ownership of fence is transferred + int readFence() + { + auto handle = readHandle(); + if (!handle || handle->numFds == 0) { + return -1; + } + + if (handle->numFds != 1) { + ALOGE("invalid fence handle with %d fds", handle->numFds); + return -1; + } + + int fd = dup(handle->data[0]); + if (fd < 0) { + ALOGW("failed to dup fence %d", handle->data[0]); + sync_wait(handle->data[0], -1); + fd = -1; + } + + return fd; + } + +private: + std::unique_ptr mQueue; + uint32_t mDataMaxSize; + std::unique_ptr mData; + + uint32_t mDataSize; + uint32_t mDataRead; + + // begin/end offsets of the current command + uint32_t mCommandBegin; + uint32_t mCommandEnd; + + hidl_vec mDataHandles; +}; + +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H diff --git a/graphics/composer/2.1/types.hal b/graphics/composer/2.1/types.hal index 9c2e1d7c95..e54031e1b7 100644 --- a/graphics/composer/2.1/types.hal +++ b/graphics/composer/2.1/types.hal @@ -23,7 +23,7 @@ enum Error : int32_t { BAD_DISPLAY = 2, /* invalid Display */ BAD_LAYER = 3, /* invalid Layer */ BAD_PARAMETER = 4, /* invalid width, height, etc. */ - HAS_CHANGES = 5, + /* 5 is reserved */ NO_RESOURCES = 6, /* temporary failure due to resource contention */ NOT_VALIDATED = 7, /* validateDisplay has not been called */ UNSUPPORTED = 8, /* permanent failure */