| /* |
| // Copyright (c) 2014 Intel Corporation |
| // |
| // 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. |
| */ |
| #include <HwcTrace.h> |
| #include <tangier/TngPlaneManager.h> |
| #include <tangier/TngPrimaryPlane.h> |
| #include <tangier/TngSpritePlane.h> |
| #include <tangier/TngOverlayPlane.h> |
| #include <tangier/TngCursorPlane.h> |
| |
| namespace android { |
| namespace intel { |
| |
| TngPlaneManager::TngPlaneManager() |
| : DisplayPlaneManager() |
| { |
| memset(&mZorder, 0, sizeof(mZorder)); |
| } |
| |
| TngPlaneManager::~TngPlaneManager() |
| { |
| } |
| |
| bool TngPlaneManager::initialize() |
| { |
| mSpritePlaneCount = 1; // Sprite D |
| mOverlayPlaneCount = 0; // Skip overlay A & C by setting count to 0 |
| mPrimaryPlaneCount = 3; // Primary A, B, C |
| mCursorPlaneCount = 3; |
| |
| return DisplayPlaneManager::initialize(); |
| } |
| |
| void TngPlaneManager::deinitialize() |
| { |
| DisplayPlaneManager::deinitialize(); |
| } |
| |
| DisplayPlane* TngPlaneManager::allocPlane(int index, int type) |
| { |
| DisplayPlane *plane = 0; |
| |
| switch (type) { |
| case DisplayPlane::PLANE_PRIMARY: |
| plane = new TngPrimaryPlane(index, index); |
| break; |
| case DisplayPlane::PLANE_SPRITE: |
| plane = new TngSpritePlane(index, 0); |
| break; |
| case DisplayPlane::PLANE_OVERLAY: |
| plane = new TngOverlayPlane(index, 0); |
| break; |
| case DisplayPlane::PLANE_CURSOR: |
| plane = new TngCursorPlane(index, index /*disp */); |
| break; |
| default: |
| ETRACE("unsupported type %d", type); |
| break; |
| } |
| if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) { |
| ETRACE("failed to initialize plane."); |
| DEINIT_AND_DELETE_OBJ(plane); |
| } |
| |
| return plane; |
| } |
| |
| bool TngPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config) |
| { |
| // check whether it's a supported z order config |
| int firstRGB = -1; |
| int lastRGB = -1; |
| int firstOverlay = -1; |
| int lastOverlay = -1; |
| |
| for (int i = 0; i < (int)config.size(); i++) { |
| const ZOrderLayer *layer = config[i]; |
| switch (layer->planeType) { |
| case DisplayPlane::PLANE_PRIMARY: |
| case DisplayPlane::PLANE_SPRITE: |
| if (firstRGB == -1) { |
| firstRGB = i; |
| lastRGB = i; |
| } else { |
| lastRGB = i; |
| } |
| break; |
| case DisplayPlane::PLANE_OVERLAY: |
| case DisplayPlane::PLANE_CURSOR: |
| if (firstOverlay == -1) { |
| firstOverlay = i; |
| lastOverlay = i; |
| } else { |
| lastOverlay = i; |
| } |
| break; |
| } |
| } |
| |
| if ((lastRGB < firstOverlay) || (firstRGB > lastOverlay)) { |
| return true; |
| } else { |
| VTRACE("invalid z order config. rgb (%d, %d) yuv (%d, %d)", |
| firstRGB, lastRGB, firstOverlay, lastOverlay); |
| return false; |
| } |
| } |
| |
| bool TngPlaneManager::assignPlanes(int dsp, ZOrderConfig& config) |
| { |
| // probe if plane is available |
| int size = (int)config.size(); |
| for (int i = 0; i < size; i++) { |
| const ZOrderLayer *layer = config.itemAt(i); |
| if (!getFreePlanes(dsp, layer->planeType)) { |
| DTRACE("no plane available for dsp %d, type %d", dsp, layer->planeType); |
| return false; |
| } |
| } |
| |
| if (config.size() == 1 && config[0]->planeType == DisplayPlane::PLANE_SPRITE) { |
| config[0]->planeType = DisplayPlane::PLANE_PRIMARY; |
| } |
| |
| // allocate planes |
| for (int i = 0; i < size; i++) { |
| ZOrderLayer *layer = config.itemAt(i); |
| layer->plane = getPlaneHelper(dsp, layer->planeType); |
| if (layer->plane == NULL) { |
| // should never happen!! |
| ETRACE("failed to assign plane for type %d", layer->planeType); |
| return false; |
| } |
| // sequence !!!!! enabling plane before setting zorder |
| // see TngSpritePlane::enablePlane implementation!!!! |
| layer->plane->enable(); |
| } |
| |
| // setup Z order |
| for (int i = 0; i < size; i++) { |
| ZOrderLayer *layer = config.itemAt(i); |
| layer->plane->setZOrderConfig(config, &mZorder); |
| } |
| |
| return true; |
| } |
| |
| void* TngPlaneManager::getZOrderConfig() const |
| { |
| return (void*)&mZorder; |
| } |
| |
| DisplayPlane* TngPlaneManager::getPlaneHelper(int dsp, int type) |
| { |
| RETURN_NULL_IF_NOT_INIT(); |
| |
| if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) { |
| ETRACE("Invalid display device %d", dsp); |
| return 0; |
| } |
| |
| int index = dsp == IDisplayDevice::DEVICE_PRIMARY ? 0 : 1; |
| |
| if (type == DisplayPlane::PLANE_PRIMARY || |
| type == DisplayPlane::PLANE_CURSOR) { |
| return getPlane(type, index); |
| } else if (type == DisplayPlane::PLANE_SPRITE) { |
| return getAnyPlane(type); |
| } else if (type == DisplayPlane::PLANE_OVERLAY) { |
| // use overlay A for pipe A and overlay C for pipe B if possible |
| DisplayPlane *plane = getPlane(type, index); |
| if (plane == NULL) { |
| plane = getPlane(type, !index); |
| } |
| return plane; |
| } else { |
| ETRACE("invalid plane type %d", type); |
| return 0; |
| } |
| } |
| |
| } // namespace intel |
| } // namespace android |
| |