|
|
/* |
|
|
// 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 <Hwcomposer.h> |
|
|
#include <Drm.h> |
|
|
#include <DisplayPlane.h> |
|
|
#include <IDisplayDevice.h> |
|
|
#include <HwcLayerList.h> |
|
|
#include <tangier/TngDisplayContext.h> |
|
|
|
|
|
|
|
|
namespace android { |
|
|
namespace intel { |
|
|
|
|
|
TngDisplayContext::TngDisplayContext() |
|
|
: mIMGDisplayDevice(0), |
|
|
mInitialized(false), |
|
|
mCount(0) |
|
|
{ |
|
|
CTRACE(); |
|
|
} |
|
|
|
|
|
TngDisplayContext::~TngDisplayContext() |
|
|
{ |
|
|
WARN_IF_NOT_DEINIT(); |
|
|
} |
|
|
|
|
|
bool TngDisplayContext::initialize() |
|
|
{ |
|
|
CTRACE(); |
|
|
|
|
|
// open frame buffer device |
|
|
const hw_device_t *gralloc; |
|
|
int err = gralloc_open_img(&gralloc); |
|
|
if (err) { |
|
|
ETRACE("failed to load gralloc module, error = %d", err); |
|
|
return false; |
|
|
} |
|
|
|
|
|
// init IMG display device |
|
|
err = gralloc_get_display_device_img(gralloc, (void **)&mIMGDisplayDevice); |
|
|
if (err) { |
|
|
ETRACE("failed to get display device, error = %d", err); |
|
|
return false; |
|
|
} |
|
|
|
|
|
mCount = 0; |
|
|
mInitialized = true; |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool TngDisplayContext::commitBegin(size_t numDisplays, hwc_display_contents_1_t **displays) |
|
|
{ |
|
|
RETURN_FALSE_IF_NOT_INIT(); |
|
|
mCount = 0; |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool TngDisplayContext::commitContents(hwc_display_contents_1_t *display, HwcLayerList *layerList) |
|
|
{ |
|
|
bool ret; |
|
|
|
|
|
RETURN_FALSE_IF_NOT_INIT(); |
|
|
|
|
|
if (!display || !layerList) { |
|
|
ETRACE("invalid parameters"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
IMG_hwc_layer_t *imgLayerList = (IMG_hwc_layer_t*)mImgLayers; |
|
|
|
|
|
for (size_t i = 0; i < display->numHwLayers; i++) { |
|
|
if (mCount >= MAXIMUM_LAYER_NUMBER) { |
|
|
ETRACE("layer count exceeds the limit"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
// check layer parameters |
|
|
if (!display->hwLayers[i].handle) { |
|
|
continue; |
|
|
} |
|
|
|
|
|
DisplayPlane* plane = layerList->getPlane(i); |
|
|
if (!plane) { |
|
|
continue; |
|
|
} |
|
|
|
|
|
ret = plane->flip(NULL); |
|
|
if (ret == false) { |
|
|
VTRACE("failed to flip plane %d", i); |
|
|
continue; |
|
|
} |
|
|
|
|
|
IMG_hwc_layer_t *imgLayer = &imgLayerList[mCount++]; |
|
|
// update IMG layer |
|
|
imgLayer->psLayer = &display->hwLayers[i]; |
|
|
imgLayer->custom = (unsigned long)plane->getContext(); |
|
|
struct intel_dc_plane_ctx *ctx = |
|
|
(struct intel_dc_plane_ctx *)imgLayer->custom; |
|
|
// update z order |
|
|
Hwcomposer& hwc = Hwcomposer::getInstance(); |
|
|
DisplayPlaneManager *pm = hwc.getPlaneManager(); |
|
|
void *config = pm->getZOrderConfig(); |
|
|
if (config) { |
|
|
memcpy(&ctx->zorder, config, sizeof(ctx->zorder)); |
|
|
} else { |
|
|
memset(&ctx->zorder, 0, sizeof(ctx->zorder)); |
|
|
} |
|
|
|
|
|
VTRACE("count %p, handle %#x, trans %#x, blending %#x" |
|
|
" sourceCrop %f,%f - %fx%f, dst %d,%d - %dx%d, custom %#x", |
|
|
mCount, |
|
|
imgLayer->psLayer->handle, |
|
|
imgLayer->psLayer->transform, |
|
|
imgLayer->psLayer->blending, |
|
|
imgLayer->psLayer->sourceCropf.left, |
|
|
imgLayer->psLayer->sourceCropf.top, |
|
|
imgLayer->psLayer->sourceCropf.right - imgLayer->psLayer->sourceCropf.left, |
|
|
imgLayer->psLayer->sourceCropf.bottom - imgLayer->psLayer->sourceCropf.top, |
|
|
imgLayer->psLayer->displayFrame.left, |
|
|
imgLayer->psLayer->displayFrame.top, |
|
|
imgLayer->psLayer->displayFrame.right - imgLayer->psLayer->displayFrame.left, |
|
|
imgLayer->psLayer->displayFrame.bottom - imgLayer->psLayer->displayFrame.top, |
|
|
imgLayer->custom); |
|
|
} |
|
|
|
|
|
layerList->postFlip(); |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool TngDisplayContext::commitEnd(size_t numDisplays, hwc_display_contents_1_t **displays) |
|
|
{ |
|
|
int releaseFenceFd = -1; |
|
|
|
|
|
VTRACE("count = %d", mCount); |
|
|
|
|
|
if (mIMGDisplayDevice && mCount) { |
|
|
int err = mIMGDisplayDevice->post(mIMGDisplayDevice, |
|
|
mImgLayers, |
|
|
mCount, |
|
|
&releaseFenceFd); |
|
|
if (err) { |
|
|
ETRACE("post failed, err = %d", err); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
// close acquire fence |
|
|
for (size_t i = 0; i < numDisplays; i++) { |
|
|
// Wait and close HWC_OVERLAY typed layer's acquire fence |
|
|
hwc_display_contents_1_t* display = displays[i]; |
|
|
if (!display) { |
|
|
continue; |
|
|
} |
|
|
|
|
|
for (size_t j = 0; j < display->numHwLayers-1; j++) { |
|
|
hwc_layer_1_t& layer = display->hwLayers[j]; |
|
|
if (layer.compositionType == HWC_OVERLAY) { |
|
|
if (layer.acquireFenceFd != -1) { |
|
|
// sync_wait(layer.acquireFenceFd, 16ms); |
|
|
close(layer.acquireFenceFd); |
|
|
layer.acquireFenceFd = -1; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
// Wait and close framebuffer target layer's acquire fence |
|
|
hwc_layer_1_t& fbt = display->hwLayers[display->numHwLayers-1]; |
|
|
if (fbt.acquireFenceFd != -1) { |
|
|
// sync_wait(fbt.acquireFencdFd, 16ms); |
|
|
close(fbt.acquireFenceFd); |
|
|
fbt.acquireFenceFd = -1; |
|
|
} |
|
|
|
|
|
// Wait and close outbuf's acquire fence |
|
|
if (display->outbufAcquireFenceFd != -1) { |
|
|
// sync_wait(display->outbufAcquireFenceFd, 16ms); |
|
|
close(display->outbufAcquireFenceFd); |
|
|
display->outbufAcquireFenceFd = -1; |
|
|
} |
|
|
} |
|
|
|
|
|
// update release fence and retire fence |
|
|
if (mCount > 0) { |
|
|
// For physical displays, dup the releaseFenceFd only for |
|
|
// HWC layers which successfully flipped to display planes |
|
|
IMG_hwc_layer_t *imgLayerList = (IMG_hwc_layer_t*)mImgLayers; |
|
|
|
|
|
for (unsigned int i = 0; i < mCount; i++) { |
|
|
IMG_hwc_layer_t *imgLayer = &imgLayerList[i]; |
|
|
imgLayer->psLayer->releaseFenceFd = |
|
|
(releaseFenceFd != -1) ? dup(releaseFenceFd) : -1; |
|
|
} |
|
|
} |
|
|
|
|
|
for (size_t i = 0; i < numDisplays; i++) { |
|
|
if (!displays[i]) { |
|
|
continue; |
|
|
} |
|
|
|
|
|
// log for layer fence status |
|
|
for (size_t j = 0; j < displays[i]->numHwLayers; j++) { |
|
|
VTRACE("handle %#p, acquiredFD %d, releaseFD %d", |
|
|
displays[i]->hwLayers[j].handle, |
|
|
displays[i]->hwLayers[j].acquireFenceFd, |
|
|
displays[i]->hwLayers[j].releaseFenceFd); |
|
|
} |
|
|
|
|
|
// retireFence is used for SurfaceFlinger to do DispSync; |
|
|
// dup releaseFenceFd for physical displays and ignore virtual |
|
|
// display; we don't distinguish between release and retire, and all |
|
|
// physical displays are using a single releaseFence; for virtual |
|
|
// display, fencing is handled by the VirtualDisplay class |
|
|
if (i < IDisplayDevice::DEVICE_VIRTUAL) { |
|
|
displays[i]->retireFenceFd = |
|
|
(releaseFenceFd != -1) ? dup(releaseFenceFd) : -1; |
|
|
} |
|
|
} |
|
|
|
|
|
// close original release fence fd |
|
|
if (releaseFenceFd != -1) { |
|
|
close(releaseFenceFd); |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool TngDisplayContext::compositionComplete() |
|
|
{ |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool TngDisplayContext::setCursorPosition(int disp, int x, int y) |
|
|
{ |
|
|
DTRACE("setCursorPosition"); |
|
|
struct intel_dc_cursor_ctx ctx; |
|
|
memset(&ctx, 0, sizeof(ctx)); |
|
|
ctx.pipe = disp; |
|
|
if (x < 0) { |
|
|
ctx.pos |= 1 << 15; |
|
|
x = -x; |
|
|
} |
|
|
if (y < 0) { |
|
|
ctx.pos |= 1 << 31; |
|
|
y = -y; |
|
|
} |
|
|
ctx.pos |= (y & 0xfff) << 16 | (x & 0xfff); |
|
|
Drm *drm = Hwcomposer::getInstance().getDrm(); |
|
|
return drm->writeIoctl(DRM_PSB_UPDATE_CURSOR_POS, &ctx, sizeof(ctx)); |
|
|
} |
|
|
|
|
|
void TngDisplayContext::deinitialize() |
|
|
{ |
|
|
mIMGDisplayDevice = 0; |
|
|
|
|
|
mCount = 0; |
|
|
mInitialized = false; |
|
|
} |
|
|
|
|
|
|
|
|
} // namespace intel |
|
|
} // namespace android
|
|
|
|