SoftwareRenderer.cpp revision 5daeb129a2c2ba3d14ccd94af283b5f561c783ea
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "SoftwareRenderer"
1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2089e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "../include/SoftwareRenderer.h"
2189e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <binder/MemoryHeapBase.h>
2389e7fff6a5d7410815f42b4a55958a59d4463180Andreas Huber#include <binder/MemoryHeapPmem.h>
240c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
255daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber#include <surfaceflinger/Surface.h>
265daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber#include <ui/android_native_buffer.h>
275daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber#include <ui/GraphicBufferMapper.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberSoftwareRenderer::SoftwareRenderer(
3210f75b8c71beb7f327e50bbac8e528af4e40fa24Andreas Huber        OMX_COLOR_FORMATTYPE colorFormat,
335daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        const sp<Surface> &surface,
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t displayWidth, size_t displayHeight,
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t decodedWidth, size_t decodedHeight)
3610f75b8c71beb7f327e50bbac8e528af4e40fa24Andreas Huber    : mColorFormat(colorFormat),
375daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber      mConverter(NULL),
385daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber      mYUVMode(None),
395daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber      mSurface(surface),
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDisplayWidth(displayWidth),
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDisplayHeight(displayHeight),
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDecodedWidth(decodedWidth),
435daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber      mDecodedHeight(decodedHeight) {
445daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    LOGI("input format = %d", mColorFormat);
455daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    LOGI("display = %d x %d, decoded = %d x %d",
465daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            mDisplayWidth, mDisplayHeight, mDecodedWidth, mDecodedHeight);
475daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
485daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    int halFormat;
495daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    switch (mColorFormat) {
505daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber#if HAS_YCBCR420_SP_ADRENO
515daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        case OMX_COLOR_FormatYUV420Planar:
525daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        {
535daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO;
545daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            mYUVMode = YUV420ToYUV420sp;
555daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            break;
565daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        }
575daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
585daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        case 0x7fa30c00:
595daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        {
605daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO;
615daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            mYUVMode = YUV420spToYUV420sp;
625daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            break;
635daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        }
645daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber#endif
655daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
665daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        default:
675daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            halFormat = HAL_PIXEL_FORMAT_RGB_565;
685daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
695daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            mConverter = new ColorConverter(
705daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                    mColorFormat, OMX_COLOR_Format16bitRGB565);
715daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            CHECK(mConverter->isValid());
725daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            break;
7389e7fff6a5d7410815f42b4a55958a59d4463180Andreas Huber    }
7489e7fff6a5d7410815f42b4a55958a59d4463180Andreas Huber
755daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK(mSurface.get() != NULL);
760c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mDecodedWidth > 0);
770c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mDecodedHeight > 0);
785daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK(mConverter == NULL || mConverter->isValid());
795daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
805daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0,
815daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            native_window_set_usage(
825daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            mSurface.get(),
835daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
845daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            | GRALLOC_USAGE_HW_TEXTURE));
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
865daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, native_window_set_buffer_count(mSurface.get(), 2));
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
885daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    // Width must be multiple of 32???
895daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, native_window_set_buffers_geometry(
905daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                mSurface.get(), mDecodedWidth, mDecodedHeight,
915daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                halFormat));
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberSoftwareRenderer::~SoftwareRenderer() {
955daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    delete mConverter;
965daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    mConverter = NULL;
975daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber}
985daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
995daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huberstatic inline size_t ALIGN(size_t x, size_t alignment) {
1005daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    return (x + alignment - 1) & ~(alignment - 1);
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid SoftwareRenderer::render(
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const void *data, size_t size, void *platformPrivate) {
1055daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    android_native_buffer_t *buf;
1065daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mSurface->dequeueBuffer(mSurface.get(), &buf));
1075daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf));
1085daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1095daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
1105daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1115daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    Rect bounds(mDecodedWidth, mDecodedHeight);
1125daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1135daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    void *dst;
1145daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mapper.lock(
1155daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));
1165daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1175daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    if (mConverter) {
1185daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        mConverter->convert(
1195daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                mDecodedWidth, mDecodedHeight,
1205daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                data, 0, dst, buf->stride * 2);
1215daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    } else if (mYUVMode == YUV420spToYUV420sp) {
1225daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        // Input and output are both YUV420sp, but the alignment requirements
1235daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        // are different.
1245daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        size_t srcYStride = mDecodedWidth;
1255daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        const uint8_t *srcY = (const uint8_t *)data;
1265daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        uint8_t *dstY = (uint8_t *)dst;
1275daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        for (size_t i = 0; i < mDecodedHeight; ++i) {
1285daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            memcpy(dstY, srcY, mDecodedWidth);
1295daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            srcY += srcYStride;
1305daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            dstY += buf->stride;
1315daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        }
1325daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1335daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        size_t srcUVStride = (mDecodedWidth + 1) & ~1;
1345daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2;
1355daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1365daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        const uint8_t *srcUV = (const uint8_t *)data
1375daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            + mDecodedHeight * mDecodedWidth;
1385daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1395daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096);
1405daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        uint8_t *dstUV = (uint8_t *)dst + dstUVOffset;
1415daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1425daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) {
1435daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            memcpy(dstUV, srcUV, (mDecodedWidth + 1) & ~1);
1445daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            srcUV += srcUVStride;
1455daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            dstUV += dstUVStride;
1465daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        }
1475daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    } else if (mYUVMode == YUV420ToYUV420sp) {
1485daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        // Input is YUV420 planar, output is YUV420sp, adhere to proper
1495daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        // alignment requirements.
1505daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        size_t srcYStride = mDecodedWidth;
1515daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        const uint8_t *srcY = (const uint8_t *)data;
1525daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        uint8_t *dstY = (uint8_t *)dst;
1535daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        for (size_t i = 0; i < mDecodedHeight; ++i) {
1545daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            memcpy(dstY, srcY, mDecodedWidth);
1555daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            srcY += srcYStride;
1565daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            dstY += buf->stride;
1575daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        }
1585daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1595daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        size_t srcUVStride = (mDecodedWidth + 1) / 2;
1605daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2;
1615daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1625daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        const uint8_t *srcU = (const uint8_t *)data
1635daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            + mDecodedHeight * mDecodedWidth;
1645daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1655daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        const uint8_t *srcV =
1665daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            srcU + ((mDecodedWidth + 1) / 2) * ((mDecodedHeight + 1) / 2);
1675daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1685daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096);
1695daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        uint8_t *dstUV = (uint8_t *)dst + dstUVOffset;
1705daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1715daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) {
1725daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            for (size_t j = 0; j < (mDecodedWidth + 1) / 2; ++j) {
1735daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                dstUV[2 * j + 1] = srcU[j];
1745daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                dstUV[2 * j] = srcV[j];
1755daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            }
1765daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            srcU += srcUVStride;
1775daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            srcV += srcUVStride;
1785daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            dstUV += dstUVStride;
1795daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        }
1805daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    } else {
1815daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        memcpy(dst, data, size);
1825daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    }
1834265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
1845daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mapper.unlock(buf->handle));
1854265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
1865daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mSurface->queueBuffer(mSurface.get(), buf));
1875daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    buf = NULL;
1884265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber}
1894265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
191