$(call emugl-import,libGLESv1_enc libGLESv2_enc lib_renderControl_enc)
LOCAL_SRC_FILES := \
- goldfish_dma.cpp \
- FormatConversions.cpp \
HostConnection.cpp \
ProcessPipe.cpp \
QemuPipeStream.cpp \
+++ /dev/null
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include "FormatConversions.h"
-
-#include <cutils/log.h>
-#include <string.h>
-
-#define DEBUG 0
-
-#if DEBUG
-#define DD(...) ALOGD(...)
-#else
-#define DD(...)
-#endif
-
-void get_yv12_offsets(int width, int height,
- uint32_t* yStride_out,
- uint32_t* cStride_out,
- uint32_t* totalSz_out) {
- uint32_t align = 16;
- uint32_t yStride = (width + (align - 1)) & ~(align-1);
- uint32_t uvStride = (yStride / 2 + (align - 1)) & ~(align-1);
- uint32_t uvHeight = height / 2;
- uint32_t sz = yStride * height + 2 * (uvHeight * uvStride);
-
- if (yStride_out) *yStride_out = yStride;
- if (cStride_out) *cStride_out = uvStride;
- if (totalSz_out) *totalSz_out = sz;
-}
-
-void get_yuv420p_offsets(int width, int height,
- uint32_t* yStride_out,
- uint32_t* cStride_out,
- uint32_t* totalSz_out) {
- uint32_t align = 1;
- uint32_t yStride = (width + (align - 1)) & ~(align-1);
- uint32_t uvStride = (yStride / 2 + (align - 1)) & ~(align-1);
- uint32_t uvHeight = height / 2;
- uint32_t sz = yStride * height + 2 * (uvHeight * uvStride);
-
- if (yStride_out) *yStride_out = yStride;
- if (cStride_out) *cStride_out = uvStride;
- if (totalSz_out) *totalSz_out = sz;
-}
-
-signed clamp_rgb(signed value) {
- if (value > 255) {
- value = 255;
- } else if (value < 0) {
- value = 0;
- }
- return value;
-}
-
-void rgb565_to_yv12(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom) {
- int align = 16;
- int yStride = (width + (align -1)) & ~(align-1);
- int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
- int yOffset = 0;
- int cSize = cStride * height/2;
-
- uint16_t *rgb_ptr0 = (uint16_t *)src;
- uint8_t *yv12_y0 = (uint8_t *)dest;
- uint8_t *yv12_v0 = yv12_y0 + yStride * height;
- uint8_t *yv12_u0 = yv12_v0 + cSize;
-
- for (int j = top; j <= bottom; ++j) {
- uint8_t *yv12_y = yv12_y0 + j * yStride;
- uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
- uint8_t *yv12_u = yv12_v + cSize;
- uint16_t *rgb_ptr = rgb_ptr0 + j * width;
- bool jeven = (j & 1) == 0;
- for (int i = left; i <= right; ++i) {
- uint8_t r = ((rgb_ptr[i]) >> 11) & 0x01f;
- uint8_t g = ((rgb_ptr[i]) >> 5) & 0x03f;
- uint8_t b = (rgb_ptr[i]) & 0x01f;
- // convert to 8bits
- // http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888
- uint8_t R = (r * 527 + 23) >> 6;
- uint8_t G = (g * 259 + 33) >> 6;
- uint8_t B = (b * 527 + 23) >> 6;
- // convert to YV12
- // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
- yv12_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8);
- bool ieven = (i & 1) == 0;
- if (jeven && ieven) {
- yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
- yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
- }
- }
- }
-}
-
-void rgb888_to_yv12(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom) {
- DD("%s convert %d by %d", __func__, width, height);
- int align = 16;
- int yStride = (width + (align -1)) & ~(align-1);
- int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
- int yOffset = 0;
- int cSize = cStride * height/2;
- int rgb_stride = 3;
-
- uint8_t *rgb_ptr0 = (uint8_t *)src;
- uint8_t *yv12_y0 = (uint8_t *)dest;
- uint8_t *yv12_v0 = yv12_y0 + yStride * height;
- uint8_t *yv12_u0 = yv12_v0 + cSize;
-
- for (int j = top; j <= bottom; ++j) {
- uint8_t *yv12_y = yv12_y0 + j * yStride;
- uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
- uint8_t *yv12_u = yv12_v + cSize;
- uint8_t *rgb_ptr = rgb_ptr0 + j * width*rgb_stride;
- bool jeven = (j & 1) == 0;
- for (int i = left; i <= right; ++i) {
- uint8_t R = rgb_ptr[i*rgb_stride];
- uint8_t G = rgb_ptr[i*rgb_stride+1];
- uint8_t B = rgb_ptr[i*rgb_stride+2];
- // convert to YV12
- // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
- yv12_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8);
- bool ieven = (i & 1) == 0;
- if (jeven && ieven) {
- yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
- yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
- }
- }
- }
-}
-
-void rgb888_to_yuv420p(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom) {
- DD("%s convert %d by %d", __func__, width, height);
- int yStride = width;
- int cStride = yStride / 2;
- int yOffset = 0;
- int cSize = cStride * height/2;
- int rgb_stride = 3;
-
- uint8_t *rgb_ptr0 = (uint8_t *)src;
- uint8_t *yv12_y0 = (uint8_t *)dest;
- uint8_t *yv12_u0 = yv12_y0 + yStride * height;
- uint8_t *yv12_v0 = yv12_u0 + cSize;
-
- for (int j = top; j <= bottom; ++j) {
- uint8_t *yv12_y = yv12_y0 + j * yStride;
- uint8_t *yv12_u = yv12_u0 + (j/2) * cStride;
- uint8_t *yv12_v = yv12_u + cStride;
- uint8_t *rgb_ptr = rgb_ptr0 + j * width*rgb_stride;
- bool jeven = (j & 1) == 0;
- for (int i = left; i <= right; ++i) {
- uint8_t R = rgb_ptr[i*rgb_stride];
- uint8_t G = rgb_ptr[i*rgb_stride+1];
- uint8_t B = rgb_ptr[i*rgb_stride+2];
- // convert to YV12
- // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
- yv12_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8);
- bool ieven = (i & 1) == 0;
- if (jeven && ieven) {
- yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
- yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
- }
- }
- }
-}
-// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
-// certain stride requirements for Y and UV respectively.
-void yv12_to_rgb565(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom) {
- DD("%s convert %d by %d", __func__, width, height);
- int align = 16;
- int yStride = (width + (align -1)) & ~(align-1);
- int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
- int yOffset = 0;
- int cSize = cStride * height/2;
-
- uint16_t *rgb_ptr0 = (uint16_t *)dest;
- uint8_t *yv12_y0 = (uint8_t *)src;
- uint8_t *yv12_v0 = yv12_y0 + yStride * height;
- uint8_t *yv12_u0 = yv12_v0 + cSize;
-
- for (int j = top; j <= bottom; ++j) {
- uint8_t *yv12_y = yv12_y0 + j * yStride;
- uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
- uint8_t *yv12_u = yv12_v + cSize;
- uint16_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1);
- for (int i = left; i <= right; ++i) {
- // convert to rgb
- // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
- signed y1 = (signed)yv12_y[i] - 16;
- signed u = (signed)yv12_u[i / 2] - 128;
- signed v = (signed)yv12_v[i / 2] - 128;
-
- signed u_b = u * 517;
- signed u_g = -u * 100;
- signed v_g = -v * 208;
- signed v_r = v * 409;
-
- signed tmp1 = y1 * 298;
- signed b1 = clamp_rgb((tmp1 + u_b) / 256);
- signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
- signed r1 = clamp_rgb((tmp1 + v_r) / 256);
-
- uint16_t rgb1 = ((r1 >> 3) << 11) | ((g1 >> 2) << 5) | (b1 >> 3);
-
- rgb_ptr[i-left] = rgb1;
- }
- }
-}
-
-// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
-// certain stride requirements for Y and UV respectively.
-void yv12_to_rgb888(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom) {
- DD("%s convert %d by %d", __func__, width, height);
- int align = 16;
- int yStride = (width + (align -1)) & ~(align-1);
- int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
- int yOffset = 0;
- int cSize = cStride * height/2;
- int rgb_stride = 3;
-
- uint8_t *rgb_ptr0 = (uint8_t *)dest;
- uint8_t *yv12_y0 = (uint8_t *)src;
- uint8_t *yv12_v0 = yv12_y0 + yStride * height;
- uint8_t *yv12_u0 = yv12_v0 + cSize;
-
- for (int j = top; j <= bottom; ++j) {
- uint8_t *yv12_y = yv12_y0 + j * yStride;
- uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
- uint8_t *yv12_u = yv12_v + cSize;
- uint8_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1) * rgb_stride;
- for (int i = left; i <= right; ++i) {
- // convert to rgb
- // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
- signed y1 = (signed)yv12_y[i] - 16;
- signed u = (signed)yv12_u[i / 2] - 128;
- signed v = (signed)yv12_v[i / 2] - 128;
-
- signed u_b = u * 517;
- signed u_g = -u * 100;
- signed v_g = -v * 208;
- signed v_r = v * 409;
-
- signed tmp1 = y1 * 298;
- signed b1 = clamp_rgb((tmp1 + u_b) / 256);
- signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
- signed r1 = clamp_rgb((tmp1 + v_r) / 256);
-
- rgb_ptr[(i-left)*rgb_stride] = r1;
- rgb_ptr[(i-left)*rgb_stride+1] = g1;
- rgb_ptr[(i-left)*rgb_stride+2] = b1;
- }
- }
-}
-
-// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
-// certain stride requirements for Y and UV respectively.
-void yuv420p_to_rgb888(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom) {
- DD("%s convert %d by %d", __func__, width, height);
- int yStride = width;
- int cStride = yStride / 2;
- int yOffset = 0;
- int cSize = cStride * height/2;
- int rgb_stride = 3;
-
- uint8_t *rgb_ptr0 = (uint8_t *)dest;
- uint8_t *yv12_y0 = (uint8_t *)src;
- uint8_t *yv12_u0 = yv12_y0 + yStride * height;
- uint8_t *yv12_v0 = yv12_u0 + cSize;
-
- for (int j = top; j <= bottom; ++j) {
- uint8_t *yv12_y = yv12_y0 + j * yStride;
- uint8_t *yv12_u = yv12_u0 + (j/2) * cStride;
- uint8_t *yv12_v = yv12_u + cSize;
- uint8_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1) * rgb_stride;
- for (int i = left; i <= right; ++i) {
- // convert to rgb
- // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
- signed y1 = (signed)yv12_y[i] - 16;
- signed u = (signed)yv12_u[i / 2] - 128;
- signed v = (signed)yv12_v[i / 2] - 128;
-
- signed u_b = u * 517;
- signed u_g = -u * 100;
- signed v_g = -v * 208;
- signed v_r = v * 409;
-
- signed tmp1 = y1 * 298;
- signed b1 = clamp_rgb((tmp1 + u_b) / 256);
- signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
- signed r1 = clamp_rgb((tmp1 + v_r) / 256);
-
- rgb_ptr[(i-left)*rgb_stride] = r1;
- rgb_ptr[(i-left)*rgb_stride+1] = g1;
- rgb_ptr[(i-left)*rgb_stride+2] = b1;
- }
- }
-}
-
-void copy_rgb_buffer(char* _dst, char* raw_data,
- int width, int height, int top, int left,
- int bpp) {
- char* dst = _dst;
- int dst_line_len = width * bpp;
- int src_line_len = width * bpp;
- char *src = (char *)raw_data + top*src_line_len + left*bpp;
- for (int y = 0; y < height; y++)
- memcpy(dst, src, dst_line_len);
- src += src_line_len;
- dst += dst_line_len;
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __GOLDFISH_FORMATCONVERSIONS_H__
-#define __GOLDFISH_FORMATCONVERSIONS_H__
-
-#include <inttypes.h>
-
-// format conversions and helper functions
-void get_yv12_offsets(int width, int height,
- uint32_t* yStride_out,
- uint32_t* cStride_out,
- uint32_t* totalSz_out);
-void get_yuv420p_offsets(int width, int height,
- uint32_t* yStride_out,
- uint32_t* cStride_out,
- uint32_t* totalSz_out);
-signed clamp_rgb(signed value);
-void rgb565_to_yv12(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom);
-void rgb888_to_yv12(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom);
-void rgb888_to_yuv420p(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom);
-void yv12_to_rgb565(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom);
-void yv12_to_rgb888(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom);
-void yuv420p_to_rgb888(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom);
-void copy_rgb_buffer(char* _dst, char* raw_data,
- int width, int height, int top, int left,
- int bpp);
-#endif
return NULL;
}
con->m_stream = stream;
- con->m_pipeFd = stream->getSocket();
}
else /* !useQemuPipe */
{
m_rcEnc = new ExtendedRCEncoderContext(m_stream, checksumHelper());
setChecksumHelper(m_rcEnc);
queryAndSetSyncImpl(m_rcEnc);
- queryAndSetDmaImpl(m_rcEnc);
processPipeInit(m_rcEnc);
}
return m_rcEnc;
}
#endif
}
-
-void HostConnection::queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc) {
- std::string glExtensions = queryGLExtensions(rcEnc);
-#if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__))
- rcEnc->setDmaImpl(DMA_IMPL_NONE);
-#else
- if (glExtensions.find(kDmaExtStr_v1) != std::string::npos) {
- rcEnc->setDmaImpl(DMA_IMPL_v1);
- } else {
- rcEnc->setDmaImpl(DMA_IMPL_NONE);
- }
-#endif
-}
#include "IOStream.h"
#include "renderControl_enc.h"
#include "ChecksumCalculator.h"
-#include "goldfish_dma.h"
#include <string>
SYNC_IMPL_NONE = 0,
SYNC_IMPL_NATIVE_SYNC = 1
};
-
// Interface:
// If this GL extension string shows up, we use
// SYNC_IMPL_NATIVE_SYNC, otherwise we use SYNC_IMPL_NONE.
// otherwise, we do not use the feature.
static const char kRCNativeSync[] = "ANDROID_EMU_native_sync_v2";
-// DMA for OpenGL
-enum DmaImpl {
- DMA_IMPL_NONE = 0,
- DMA_IMPL_v1 = 1,
-};
-
-static const char kDmaExtStr_v1[] = "ANDROID_EMU_dma_v1";
-
// ExtendedRCEncoderContext is an extended version of renderControl_encoder_context_t
// that will be used to track SyncImpl.
class ExtendedRCEncoderContext : public renderControl_encoder_context_t {
public:
ExtendedRCEncoderContext(IOStream *stream, ChecksumCalculator *checksumCalculator)
- : renderControl_encoder_context_t(stream, checksumCalculator) {
- m_dmaCxt = NULL;
- }
+ : renderControl_encoder_context_t(stream, checksumCalculator) { }
void setSyncImpl(SyncImpl syncImpl) { m_syncImpl = syncImpl; }
- void setDmaImpl(DmaImpl dmaImpl) { m_dmaImpl = dmaImpl; }
bool hasNativeSync() const { return m_syncImpl == SYNC_IMPL_NATIVE_SYNC; }
- DmaImpl getDmaVersion() const { return m_dmaImpl; }
- void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
- virtual uint64_t lockAndWriteDma(void* data, uint32_t size) {
- ALOGV("%s: call", __FUNCTION__);
- if (!m_dmaCxt) {
- ALOGE("%s: ERROR: No DMA context bound!",
- __FUNCTION__);
- return 0;
- }
- goldfish_dma_lock(m_dmaCxt);
- goldfish_dma_write(m_dmaCxt, data, size);
- uint64_t paddr = goldfish_dma_guest_paddr(m_dmaCxt);
- ALOGV("%s: paddr=0x%llx", __FUNCTION__, paddr);
- return paddr;
- }
private:
SyncImpl m_syncImpl;
- DmaImpl m_dmaImpl;
- struct goldfish_dma_context* m_dmaCxt;
};
class HostConnection
bool isGrallocOnly() const { return m_grallocOnly; }
- int getPipeFd() const { return m_pipeFd; }
-
private:
HostConnection();
static gl_client_context_t *s_getGLContext();
// should be called when m_rcEnc is created
void setChecksumHelper(ExtendedRCEncoderContext *rcEnc);
void queryAndSetSyncImpl(ExtendedRCEncoderContext *rcEnc);
- void queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc);
private:
IOStream *m_stream;
ChecksumCalculator m_checksumHelper;
std::string m_glExtensions;
bool m_grallocOnly;
- int m_pipeFd;
};
#endif
#else // PLATFORM_SDK_VERSION
m_sock = qemu_pipe_open("opengles");
#endif // PLATFORM_SDK_VERSION
- if (!valid()) {
- ALOGE("%s: failed with fd %d errno %d", __FUNCTION__, m_sock, errno);
- return -1;
- }
+ if (!valid()) return -1;
return 0;
}
return retval;
}
-int QemuPipeStream::getSocket() const {
- return m_sock;
-}
-
const unsigned char *QemuPipeStream::readFully(void *buf, size_t len)
{
//DBG(">> QemuPipeStream::readFully %d\n", len);
virtual int writeFully(const void *buf, size_t len);
- int getSocket() const;
private:
int m_sock;
size_t m_bufsize;
+++ /dev/null
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <cutils/log.h>
-#include <sys/mman.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <hardware/qemu_pipe.h>
-
-#include "goldfish_dma.h"
-
-int goldfish_dma_lock(struct goldfish_dma_context* cxt) {
- struct goldfish_dma_ioctl_info info;
-
- return ioctl(cxt->fd, GOLDFISH_DMA_IOC_LOCK, &info);
-}
-
-int goldfish_dma_unlock(struct goldfish_dma_context* cxt) {
- struct goldfish_dma_ioctl_info info;
-
- return ioctl(cxt->fd, GOLDFISH_DMA_IOC_UNLOCK, &info);
-}
-
-int goldfish_dma_create_region(uint32_t sz, struct goldfish_dma_context* res) {
-
- res->fd = qemu_pipe_open("opengles");
- res->mapped = NULL;
- res->sz = 0;
-
- if (res->fd > 0) {
- // now alloc
- struct goldfish_dma_ioctl_info info;
- info.size = sz;
- int alloc_res = ioctl(res->fd, GOLDFISH_DMA_IOC_CREATE_REGION, &info);
-
- if (alloc_res) {
- ALOGE("%s: failed to allocate DMA region. errno=%d",
- __FUNCTION__, errno);
- close(res->fd);
- res->fd = -1;
- return alloc_res;
- }
-
- res->sz = sz;
- ALOGV("%s: successfully allocated goldfish DMA region with size %lu cxt=%p",
- __FUNCTION__, sz, res);
- return 0;
- } else {
- ALOGE("%s: could not obtain fd to device! fd %d errno=%d\n",
- __FUNCTION__, res->fd, errno);
- return ENODEV;
- }
-}
-
-void* goldfish_dma_map(struct goldfish_dma_context* cxt) {
- ALOGV("%s: on fd %d errno=%d", __FUNCTION__, cxt->fd, errno);
- cxt->mapped = mmap(0, cxt->sz, PROT_WRITE, MAP_SHARED, cxt->fd, 0);
- ALOGV("%s: mapped addr=%p errno=%d", __FUNCTION__, cxt->mapped, errno);
-
- if (cxt->mapped == MAP_FAILED) {
- cxt->mapped = NULL;
- }
- return cxt->mapped;
-}
-
-int goldfish_dma_unmap(struct goldfish_dma_context* cxt) {
- munmap(cxt->mapped, cxt->sz);
- cxt->mapped = NULL;
- cxt->sz = 0;
- return 0;
-}
-
-void goldfish_dma_write(struct goldfish_dma_context* cxt,
- void* to_write,
- uint32_t sz) {
- ALOGV("%s: mapped addr=%p", __FUNCTION__, cxt->mapped);
- memcpy(cxt->mapped, to_write, sz);
-}
-
-void goldfish_dma_free(goldfish_dma_context* cxt) {
- struct goldfish_dma_ioctl_info info;
- close(cxt->fd);
-}
-
-uint64_t goldfish_dma_guest_paddr(struct goldfish_dma_context* cxt) {
- struct goldfish_dma_ioctl_info info;
- ioctl(cxt->fd, GOLDFISH_DMA_IOC_GETOFF, &info);
- return info.phys_begin;
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_DMA_H
-#define ANDROID_INCLUDE_HARDWARE_GOLDFISH_DMA_H
-
-#include <errno.h>
-#include <linux/ioctl.h>
-#include <linux/types.h>
-#include <sys/cdefs.h>
-#include <fcntl.h>
-#include <stdlib.h>
-
-/* There is an ioctl associated with goldfish dma driver.
- * Make it conflict with ioctls that are not likely to be used
- * in the emulator.
- * 'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict!
- * 'G' 00-0F linux/gigaset_dev.h conflict!
- */
-#define GOLDFISH_DMA_IOC_MAGIC 'G'
-
-#define GOLDFISH_DMA_IOC_LOCK _IOWR(GOLDFISH_DMA_IOC_MAGIC, 0, struct goldfish_dma_ioctl_info)
-#define GOLDFISH_DMA_IOC_UNLOCK _IOWR(GOLDFISH_DMA_IOC_MAGIC, 1, struct goldfish_dma_ioctl_info)
-#define GOLDFISH_DMA_IOC_GETOFF _IOWR(GOLDFISH_DMA_IOC_MAGIC, 2, struct goldfish_dma_ioctl_info)
-#define GOLDFISH_DMA_IOC_CREATE_REGION _IOWR(GOLDFISH_DMA_IOC_MAGIC, 3, struct goldfish_dma_ioctl_info)
-
-struct goldfish_dma_ioctl_info {
- uint64_t phys_begin;
- uint64_t size;
-};
-
-// userspace interface
-struct goldfish_dma_context {
- int fd;
- void* mapped;
- uint64_t sz; // size of reservation
-};
-
-int goldfish_dma_lock(struct goldfish_dma_context* cxt);
-int goldfish_dma_unlock(struct goldfish_dma_context* cxt);
-int goldfish_dma_create_region(uint32_t sz, struct goldfish_dma_context* res);
-
-void* goldfish_dma_map(struct goldfish_dma_context* cxt);
-int goldfish_dma_unmap(struct goldfish_dma_context* cxt);
-
-void goldfish_dma_write(struct goldfish_dma_context* cxt,
- void* to_write,
- uint32_t sz);
-
-void goldfish_dma_free(goldfish_dma_context* cxt);
-uint64_t goldfish_dma_guest_paddr(struct goldfish_dma_context* cxt);
-
-#endif
#include <hardware/gralloc.h>
#include <cutils/native_handle.h>
-#include "goldfish_dma.h"
-
#define BUFFER_HANDLE_MAGIC ((int)0xabfabfab)
#define CB_HANDLE_NUM_INTS(nfds) (int)((sizeof(cb_handle_t) - (nfds)*sizeof(int)) / sizeof(int))
-// Tell the emulator which gralloc formats
-// need special handling.
-enum EmulatorFrameworkFormat {
- FRAMEWORK_FORMAT_GL_COMPATIBLE = 0,
- FRAMEWORK_FORMAT_YV12 = 1,
- FRAMEWORK_FORMAT_YUV_420_888 = 2,
-};
-
//
// Our buffer handle structure
//
cb_handle_t(int p_fd, int p_ashmemSize, int p_usage,
int p_width, int p_height, int p_frameworkFormat,
- int p_format, int p_glFormat, int p_glType,
- EmulatorFrameworkFormat p_emuFrameworkFormat) :
+ int p_format, int p_glFormat, int p_glType) :
fd(p_fd),
magic(BUFFER_HANDLE_MAGIC),
usage(p_usage),
lockedTop(0),
lockedWidth(0),
lockedHeight(0),
- hostHandle(0),
- emuFrameworkFormat(p_emuFrameworkFormat)
+ hostHandle(0)
{
- goldfish_dma.fd = -1;
- dmafd = -1;
version = sizeof(native_handle);
numFds = 0;
numInts = CB_HANDLE_NUM_INTS(numFds);
void setFd(int p_fd) {
if (p_fd >= 0) {
- numFds++;
+ numFds = 1;
}
- fd = p_fd;
- numInts = CB_HANDLE_NUM_INTS(numFds);
- }
-
- void setDmaFd(int fd) {
- if (fd >= 0) {
- numFds++;
+ else {
+ numFds = 0;
}
- dmafd = fd;
+ fd = p_fd;
numInts = CB_HANDLE_NUM_INTS(numFds);
}
// file-descriptors
int fd; // ashmem fd (-1 of ashmem region did not allocated, i.e. no SW access needed)
- int dmafd; // goldfish dma fd.
// ints
int magic; // magic number in order to validate a pointer to be a cb_handle_t
int lockedWidth;
int lockedHeight;
uint32_t hostHandle;
-
- goldfish_dma_context goldfish_dma;
- uint32_t goldfish_dma_buf_size;
- EmulatorFrameworkFormat emuFrameworkFormat;
};
return EGL_FALSE;
}
- rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), pixelFormat);
+ rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
+ pixelFormat);
if (!rcColorBuffer) {
ALOGE("rcCreateColorBuffer returned 0");
return EGL_FALSE;
#include <dlfcn.h>
#include <sys/mman.h>
#include "gralloc_cb.h"
-#include "goldfish_dma.h"
-#include "FormatConversions.h"
#include "HostConnection.h"
#include "ProcessPipe.h"
#include "glUtils.h"
#include <cutils/log.h>
-#include <cutils/klog.h>
#include <cutils/properties.h>
-#define KINFO(x...) KLOG_ERROR("gralloc", x)
-
/* Set to 1 or 2 to enable debug traces */
#define DEBUG 0
void *addr = mmap(0, cb->ashmemSize, PROT_READ | PROT_WRITE,
MAP_SHARED, cb->fd, 0);
if (addr == MAP_FAILED) {
- ALOGE("%s: failed to map ashmem region!", __FUNCTION__);
return -errno;
}
#define DEFINE_HOST_CONNECTION \
HostConnection *hostCon = HostConnection::get(); \
- ExtendedRCEncoderContext *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
+ renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
+
+#define EXIT_GRALLOCONLY_HOST_CONNECTION \
+ HostConnection *hostCon = HostConnection::get(); \
+ if (hostCon && hostCon->isGrallocOnly()) { \
+ ALOGD("%s: exiting HostConnection (is buffer-handling thread)", \
+ __FUNCTION__); \
+ HostConnection::exit(); \
+ }
#define DEFINE_AND_VALIDATE_HOST_CONNECTION \
HostConnection *hostCon = HostConnection::get(); \
ALOGE("gralloc: Failed to get host connection\n"); \
return -EIO; \
} \
- ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
+ renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
if (!rcEnc) { \
ALOGE("gralloc: Failed to get renderControl encoder context\n"); \
return -EIO; \
#define HAL_PIXEL_FORMAT_YCbCr_420_888 0xFFFFFFFF
#endif
-static void updateHostColorBuffer(cb_handle_t* cb,
- bool doLocked,
- char* pixels) {
- D("%s: call. doLocked=%d", __FUNCTION__, doLocked);
- DEFINE_HOST_CONNECTION;
- int bpp = glUtilsPixelBitSize(cb->glFormat, cb->glType) >> 3;
- int left = doLocked ? cb->lockedLeft : 0;
- int top = doLocked ? cb->lockedTop : 0;
- int width = doLocked ? cb->lockedWidth : cb->width;
- int height = doLocked ? cb->lockedHeight : cb->height;
-
- char* to_send = pixels;
- uint32_t rgbSz = width * height * bpp;
- uint32_t send_buffer_size = rgbSz;
- bool is_rgb_format =
- cb->frameworkFormat != HAL_PIXEL_FORMAT_YV12 &&
- cb->frameworkFormat != HAL_PIXEL_FORMAT_YCbCr_420_888;
-
- char* convertedBuf = NULL;
- if ((doLocked && is_rgb_format) ||
- (cb->goldfish_dma.fd < 0 &&
- (doLocked || !is_rgb_format))) {
- convertedBuf = new char[rgbSz];
- to_send = convertedBuf;
- send_buffer_size = rgbSz;
- }
-
- if (doLocked && is_rgb_format) {
- copy_rgb_buffer(to_send, pixels, width, height, top, left, bpp);
- }
-
- if (cb->goldfish_dma.fd > 0) {
- if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
- get_yv12_offsets(width, height, NULL, NULL,
- &send_buffer_size);
- }
- if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- get_yuv420p_offsets(width, height, NULL, NULL,
- &send_buffer_size);
- }
-
- rcEnc->bindDmaContext(&cb->goldfish_dma);
- D("%s: call. dma update with sz=%u", __FUNCTION__, send_buffer_size);
- rcEnc->rcUpdateColorBufferDMA(rcEnc, cb->hostHandle,
- left, top, width, height,
- cb->glFormat, cb->glType,
- to_send, send_buffer_size);
- } else {
- if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
- yv12_to_rgb888(to_send, pixels,
- width, height, left, top,
- left + width - 1, top + height - 1);
- }
- if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- yuv420p_to_rgb888(to_send, pixels,
- width, height, left, top,
- left + width - 1, top + height - 1);
- }
- rcEnc->rcUpdateColorBuffer(rcEnc, cb->hostHandle,
- left, top, width, height,
- cb->glFormat, cb->glType, to_send);
- }
-
- if (convertedBuf) delete [] convertedBuf;
-}
-
//
// gralloc device functions (alloc interface)
//
GLenum glFormat = 0;
GLenum glType = 0;
- EmulatorFrameworkFormat selectedEmuFrameworkFormat = FRAMEWORK_FORMAT_GL_COMPATIBLE;
int bpp = 0;
int align = 1;
// We are going to use RGB888 on the host
glFormat = GL_RGB;
glType = GL_UNSIGNED_BYTE;
- selectedEmuFrameworkFormat = FRAMEWORK_FORMAT_YV12;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_888:
ALOGD("%s: 420_888 format experimental path. "
// We are going to use RGB888 on the host
glFormat = GL_RGB;
glType = GL_UNSIGNED_BYTE;
- selectedEmuFrameworkFormat = FRAMEWORK_FORMAT_YUV_420_888;
break;
default:
ALOGE("gralloc_alloc: Unknown format %d", format);
// round to page size;
ashmem_size = (ashmem_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
- ALOGD("%s: Creating ashmem region of size %lu\n", __FUNCTION__, ashmem_size);
fd = ashmem_create_region("gralloc-buffer", ashmem_size);
if (fd < 0) {
ALOGE("gralloc_alloc failed to create ashmem region: %s\n",
cb_handle_t *cb = new cb_handle_t(fd, ashmem_size, usage,
w, h, frameworkFormat, format,
- glFormat, glType, selectedEmuFrameworkFormat);
+ glFormat, glType);
- DEFINE_HOST_CONNECTION;
if (ashmem_size > 0) {
-
//
// map ashmem region if exist
//
}
cb->setFd(fd);
-
- if (rcEnc->getDmaVersion() > 0) {
- D("%s: creating goldfish dma region of size %lu (cb fd %d)\n", __FUNCTION__, ashmem_size, cb->fd);
- err = goldfish_dma_create_region(ashmem_size, &cb->goldfish_dma);
- if (err) {
- ALOGE("%s: Failed to create goldfish DMA region", __FUNCTION__);
- } else {
- goldfish_dma_map(&cb->goldfish_dma);
- cb->setDmaFd(cb->goldfish_dma.fd);
- D("%s: done, cbfd %d dmafd1 %d dmafd2 %d", __FUNCTION__, cb->fd, cb->goldfish_dma.fd, cb->dmafd);
- }
- } else {
- cb->goldfish_dma.fd = -1;
- }
- } else {
- cb->goldfish_dma.fd = -1;
}
//
GRALLOC_USAGE_HW_2D |
GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_SW_READ_MASK) ) {
#endif // PLATFORM_SDK_VERSION
+ ALOGD("%s: format %d and usage 0x%x imply creation of host color buffer",
+ __FUNCTION__, frameworkFormat, usage);
+ DEFINE_HOST_CONNECTION;
if (hostCon && rcEnc) {
- if (cb->goldfish_dma.fd > 0) {
- cb->hostHandle = rcEnc->rcCreateColorBufferDMA(rcEnc, w, h, glFormat, cb->emuFrameworkFormat);
- } else {
- cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, glFormat);
- }
+ cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, glFormat);
D("Created host ColorBuffer 0x%x\n", cb->hostHandle);
}
static int gralloc_free(alloc_device_t* dev,
buffer_handle_t handle)
{
- D("%s: start", __FUNCTION__);
- cb_handle_t *cb = (cb_handle_t *)handle;
+ const cb_handle_t *cb = (const cb_handle_t *)handle;
if (!cb_handle_t::validate((cb_handle_t*)cb)) {
ERR("gralloc_free: invalid handle");
return -EINVAL;
}
close(cb->fd);
}
- if (cb->dmafd > 0) {
- D("%s: unmap and free dma fd %d\n", __FUNCTION__, cb->dmafd);
- cb->goldfish_dma.fd = cb->dmafd;
- if (cb->ashmemSize > 0 && cb->ashmemBase) {
- goldfish_dma_unmap(&cb->goldfish_dma);
- }
- goldfish_dma_free(&cb->goldfish_dma);
- D("%s: closed dma fd %d\n", __FUNCTION__, cb->dmafd);
- }
- D("%s: done", __FUNCTION__);
// remove it from the allocated list
gralloc_device_t *grdev = (gralloc_device_t *)dev;
pthread_mutex_lock(&grdev->lock);
delete cb;
- D("%s: exit", __FUNCTION__);
return 0;
}
static int gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
- D("%s: start", __FUNCTION__);
pthread_once(&sFallbackOnce, fallback_init);
if (sFallback != NULL) {
return sFallback->registerBuffer(sFallback, handle);
return -err;
}
cb->mappedPid = getpid();
- D("%s: checking to map goldfish dma", __FUNCTION__);
- if (cb->dmafd > 0) {
- D("%s: attempting to goldfish dma mmap. cbfd %d dmafd1 %d dmafd2 %d", __FUNCTION__, cb->fd, cb->goldfish_dma.fd, cb->dmafd);
- D("cxt=%p curr pid %d mapped pid %d",
- &cb->goldfish_dma,
- (int)getpid(),
- cb->mappedPid);
- if (cb->goldfish_dma.fd != cb->dmafd) {
- cb->goldfish_dma.fd = cb->dmafd;
- }
- goldfish_dma_map(&cb->goldfish_dma);
- }
}
return 0;
static int gralloc_unregister_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
- D("%s: call", __FUNCTION__);
if (sFallback != NULL) {
return sFallback->unregisterBuffer(sFallback, handle);
}
// (through register_buffer)
//
if (cb->ashmemSize > 0 && cb->mappedPid == getpid()) {
- DEFINE_AND_VALIDATE_HOST_CONNECTION;
void *vaddr;
int err = munmap((void *)cb->ashmemBase, cb->ashmemSize);
if (err) {
}
cb->ashmemBase = 0;
cb->mappedPid = 0;
- D("%s: Unregister buffer previous mapped to pid %d", __FUNCTION__, getpid());
- if (cb->dmafd > 0) {
- cb->goldfish_dma.fd = cb->dmafd;
- D("%s: Unmap dma fd %d (%d)", __FUNCTION__, cb->dmafd, cb->goldfish_dma.fd);
- goldfish_dma_unmap(&cb->goldfish_dma);
- }
}
-
D("gralloc_unregister_buffer(%p) done\n", cb);
+
+ EXIT_GRALLOCONLY_HOST_CONNECTION;
return 0;
}
+static signed clamp_rgb(signed value) {
+ if (value > 255) {
+ value = 255;
+ } else if (value < 0) {
+ value = 0;
+ }
+ return value;
+}
+
+static void rgb565_to_yv12(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom) {
+ int align = 16;
+ int yStride = (width + (align -1)) & ~(align-1);
+ int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
+ int yOffset = 0;
+ int cSize = cStride * height/2;
+
+ uint16_t *rgb_ptr0 = (uint16_t *)src;
+ uint8_t *yv12_y0 = (uint8_t *)dest;
+ uint8_t *yv12_v0 = yv12_y0 + yStride * height;
+ uint8_t *yv12_u0 = yv12_v0 + cSize;
+
+ for (int j = top; j <= bottom; ++j) {
+ uint8_t *yv12_y = yv12_y0 + j * yStride;
+ uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
+ uint8_t *yv12_u = yv12_v + cSize;
+ uint16_t *rgb_ptr = rgb_ptr0 + j * width;
+ bool jeven = (j & 1) == 0;
+ for (int i = left; i <= right; ++i) {
+ uint8_t r = ((rgb_ptr[i]) >> 11) & 0x01f;
+ uint8_t g = ((rgb_ptr[i]) >> 5) & 0x03f;
+ uint8_t b = (rgb_ptr[i]) & 0x01f;
+ // convert to 8bits
+ // http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888
+ uint8_t R = (r * 527 + 23) >> 6;
+ uint8_t G = (g * 259 + 33) >> 6;
+ uint8_t B = (b * 527 + 23) >> 6;
+ // convert to YV12
+ // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+ yv12_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8);
+ bool ieven = (i & 1) == 0;
+ if (jeven && ieven) {
+ yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
+ yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
+ }
+ }
+ }
+}
+static void rgb888_to_yv12(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom) {
+ DD("%s convert %d by %d", __func__, width, height);
+ int align = 16;
+ int yStride = (width + (align -1)) & ~(align-1);
+ int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
+ int yOffset = 0;
+ int cSize = cStride * height/2;
+ int rgb_stride = 3;
+
+ uint8_t *rgb_ptr0 = (uint8_t *)src;
+ uint8_t *yv12_y0 = (uint8_t *)dest;
+ uint8_t *yv12_v0 = yv12_y0 + yStride * height;
+ uint8_t *yv12_u0 = yv12_v0 + cSize;
+
+ for (int j = top; j <= bottom; ++j) {
+ uint8_t *yv12_y = yv12_y0 + j * yStride;
+ uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
+ uint8_t *yv12_u = yv12_v + cSize;
+ uint8_t *rgb_ptr = rgb_ptr0 + j * width*rgb_stride;
+ bool jeven = (j & 1) == 0;
+ for (int i = left; i <= right; ++i) {
+ uint8_t R = rgb_ptr[i*rgb_stride];
+ uint8_t G = rgb_ptr[i*rgb_stride+1];
+ uint8_t B = rgb_ptr[i*rgb_stride+2];
+ // convert to YV12
+ // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+ yv12_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8);
+ bool ieven = (i & 1) == 0;
+ if (jeven && ieven) {
+ yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
+ yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
+ }
+ }
+ }
+}
+
+static void rgb888_to_yuv420p(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom) {
+ DD("%s convert %d by %d", __func__, width, height);
+ int yStride = width;
+ int cStride = yStride / 2;
+ int yOffset = 0;
+ int cSize = cStride * height/2;
+ int rgb_stride = 3;
+
+ uint8_t *rgb_ptr0 = (uint8_t *)src;
+ uint8_t *yv12_y0 = (uint8_t *)dest;
+ uint8_t *yv12_u0 = yv12_y0 + yStride * height;
+ uint8_t *yv12_v0 = yv12_u0 + cSize;
+
+ for (int j = top; j <= bottom; ++j) {
+ uint8_t *yv12_y = yv12_y0 + j * yStride;
+ uint8_t *yv12_u = yv12_u0 + (j/2) * cStride;
+ uint8_t *yv12_v = yv12_u + cStride;
+ uint8_t *rgb_ptr = rgb_ptr0 + j * width*rgb_stride;
+ bool jeven = (j & 1) == 0;
+ for (int i = left; i <= right; ++i) {
+ uint8_t R = rgb_ptr[i*rgb_stride];
+ uint8_t G = rgb_ptr[i*rgb_stride+1];
+ uint8_t B = rgb_ptr[i*rgb_stride+2];
+ // convert to YV12
+ // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+ yv12_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8);
+ bool ieven = (i & 1) == 0;
+ if (jeven && ieven) {
+ yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
+ yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
+ }
+ }
+ }
+}
static int gralloc_lock(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
return 0;
}
+// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
+// certain stride requirements for Y and UV respectively.
+static void yv12_to_rgb565(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom) {
+ DD("%s convert %d by %d", __func__, width, height);
+ int align = 16;
+ int yStride = (width + (align -1)) & ~(align-1);
+ int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
+ int yOffset = 0;
+ int cSize = cStride * height/2;
+
+ uint16_t *rgb_ptr0 = (uint16_t *)dest;
+ uint8_t *yv12_y0 = (uint8_t *)src;
+ uint8_t *yv12_v0 = yv12_y0 + yStride * height;
+ uint8_t *yv12_u0 = yv12_v0 + cSize;
+
+ for (int j = top; j <= bottom; ++j) {
+ uint8_t *yv12_y = yv12_y0 + j * yStride;
+ uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
+ uint8_t *yv12_u = yv12_v + cSize;
+ uint16_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1);
+ for (int i = left; i <= right; ++i) {
+ // convert to rgb
+ // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
+ signed y1 = (signed)yv12_y[i] - 16;
+ signed u = (signed)yv12_u[i / 2] - 128;
+ signed v = (signed)yv12_v[i / 2] - 128;
+
+ signed u_b = u * 517;
+ signed u_g = -u * 100;
+ signed v_g = -v * 208;
+ signed v_r = v * 409;
+
+ signed tmp1 = y1 * 298;
+ signed b1 = clamp_rgb((tmp1 + u_b) / 256);
+ signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
+ signed r1 = clamp_rgb((tmp1 + v_r) / 256);
+
+ uint16_t rgb1 = ((r1 >> 3) << 11) | ((g1 >> 2) << 5) | (b1 >> 3);
+
+ rgb_ptr[i-left] = rgb1;
+ }
+ }
+}
+
+// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
+// certain stride requirements for Y and UV respectively.
+static void yv12_to_rgb888(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom) {
+ DD("%s convert %d by %d", __func__, width, height);
+ int align = 16;
+ int yStride = (width + (align -1)) & ~(align-1);
+ int cStride = (yStride / 2 + (align - 1)) & ~(align-1);
+ int yOffset = 0;
+ int cSize = cStride * height/2;
+ int rgb_stride = 3;
+
+ uint8_t *rgb_ptr0 = (uint8_t *)dest;
+ uint8_t *yv12_y0 = (uint8_t *)src;
+ uint8_t *yv12_v0 = yv12_y0 + yStride * height;
+ uint8_t *yv12_u0 = yv12_v0 + cSize;
+
+ for (int j = top; j <= bottom; ++j) {
+ uint8_t *yv12_y = yv12_y0 + j * yStride;
+ uint8_t *yv12_v = yv12_v0 + (j/2) * cStride;
+ uint8_t *yv12_u = yv12_v + cSize;
+ uint8_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1) * rgb_stride;
+ for (int i = left; i <= right; ++i) {
+ // convert to rgb
+ // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
+ signed y1 = (signed)yv12_y[i] - 16;
+ signed u = (signed)yv12_u[i / 2] - 128;
+ signed v = (signed)yv12_v[i / 2] - 128;
+
+ signed u_b = u * 517;
+ signed u_g = -u * 100;
+ signed v_g = -v * 208;
+ signed v_r = v * 409;
+
+ signed tmp1 = y1 * 298;
+ signed b1 = clamp_rgb((tmp1 + u_b) / 256);
+ signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
+ signed r1 = clamp_rgb((tmp1 + v_r) / 256);
+
+ rgb_ptr[(i-left)*rgb_stride] = r1;
+ rgb_ptr[(i-left)*rgb_stride+1] = g1;
+ rgb_ptr[(i-left)*rgb_stride+2] = b1;
+ }
+ }
+}
+
+// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
+// certain stride requirements for Y and UV respectively.
+static void yuv420p_to_rgb888(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom) {
+ DD("%s convert %d by %d", __func__, width, height);
+ int yStride = width;
+ int cStride = yStride / 2;
+ int yOffset = 0;
+ int cSize = cStride * height/2;
+ int rgb_stride = 3;
+
+ uint8_t *rgb_ptr0 = (uint8_t *)dest;
+ uint8_t *yv12_y0 = (uint8_t *)src;
+ uint8_t *yv12_u0 = yv12_y0 + yStride * height;
+ uint8_t *yv12_v0 = yv12_u0 + cSize;
+
+ for (int j = top; j <= bottom; ++j) {
+ uint8_t *yv12_y = yv12_y0 + j * yStride;
+ uint8_t *yv12_u = yv12_u0 + (j/2) * cStride;
+ uint8_t *yv12_v = yv12_u + cSize;
+ uint8_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1) * rgb_stride;
+ for (int i = left; i <= right; ++i) {
+ // convert to rgb
+ // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
+ signed y1 = (signed)yv12_y[i] - 16;
+ signed u = (signed)yv12_u[i / 2] - 128;
+ signed v = (signed)yv12_v[i / 2] - 128;
+
+ signed u_b = u * 517;
+ signed u_g = -u * 100;
+ signed v_g = -v * 208;
+ signed v_r = v * 409;
+
+ signed tmp1 = y1 * 298;
+ signed b1 = clamp_rgb((tmp1 + u_b) / 256);
+ signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
+ signed r1 = clamp_rgb((tmp1 + v_r) / 256);
+
+ rgb_ptr[(i-left)*rgb_stride] = r1;
+ rgb_ptr[(i-left)*rgb_stride+1] = g1;
+ rgb_ptr[(i-left)*rgb_stride+2] = b1;
+ }
+ }
+}
+
static int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle)
{
char* rgb_addr = (char *)cpu_addr;
if (cb->lockedWidth < cb->width || cb->lockedHeight < cb->height) {
- updateHostColorBuffer(cb, true, rgb_addr);
+ int bpp = glUtilsPixelBitSize(cb->glFormat, cb->glType) >> 3;
+ char *tmpBuf = new char[cb->lockedWidth * cb->lockedHeight * bpp];
+ if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
+ yv12_to_rgb888(tmpBuf, (char*)cpu_addr, cb->width, cb->height, cb->lockedLeft,
+ cb->lockedTop, cb->lockedLeft+cb->lockedWidth-1, cb->lockedTop+cb->lockedHeight-1);
+ } else if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ yuv420p_to_rgb888(tmpBuf, (char*)cpu_addr, cb->width, cb->height, cb->lockedLeft,
+ cb->lockedTop, cb->lockedLeft+cb->lockedWidth-1, cb->lockedTop+cb->lockedHeight-1);
+ } else {
+ int dst_line_len = cb->lockedWidth * bpp;
+ int src_line_len = cb->width * bpp;
+ char *src = (char *)rgb_addr + cb->lockedTop*src_line_len + cb->lockedLeft*bpp;
+ char *dst = tmpBuf;
+ for (int y=0; y<cb->lockedHeight; y++) {
+ memcpy(dst, src, dst_line_len);
+ src += src_line_len;
+ dst += dst_line_len;
+ }
+ }
+
+ rcEnc->rcUpdateColorBuffer(rcEnc, cb->hostHandle,
+ cb->lockedLeft, cb->lockedTop,
+ cb->lockedWidth, cb->lockedHeight,
+ cb->glFormat, cb->glType,
+ tmpBuf);
+
+ delete [] tmpBuf;
}
else {
- updateHostColorBuffer(cb, false, rgb_addr);
+ char* rgbBuf = 0;
+ if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
+ // for this format, we need to convert to RGB888 format
+ // before updating host
+ rgbBuf = new char[cb->width * cb->height * 3];
+ yv12_to_rgb888(rgbBuf, (char*)cpu_addr, cb->width, cb->height, 0, 0, cb->width-1, cb->height-1);
+ rgb_addr = rgbBuf;
+ } else if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ // for this format, we need to convert to RGB888 format
+ // before updating host
+ rgbBuf = new char[cb->width * cb->height * 3];
+ yuv420p_to_rgb888(rgbBuf, (char*)cpu_addr, cb->width, cb->height, 0, 0, cb->width-1, cb->height-1);
+ rgb_addr = rgbBuf;
+ }
+
+ rcEnc->rcUpdateColorBuffer(rcEnc, cb->hostHandle, 0, 0,
+ cb->width, cb->height,
+ cb->glFormat, cb->glType,
+ rgb_addr);
+ if (rgbBuf) {
+ delete [] rgbBuf;
+ }
}
DD("gralloc_unlock success. cpu_addr: %p", cpu_addr);
rcFlushWindowColorBufferAsync = (rcFlushWindowColorBufferAsync_client_proc_t) getProc("rcFlushWindowColorBufferAsync", userData);
rcDestroySyncKHR = (rcDestroySyncKHR_client_proc_t) getProc("rcDestroySyncKHR", userData);
rcSetPuid = (rcSetPuid_client_proc_t) getProc("rcSetPuid", userData);
- rcUpdateColorBufferDMA = (rcUpdateColorBufferDMA_client_proc_t) getProc("rcUpdateColorBufferDMA", userData);
- rcCreateColorBufferDMA = (rcCreateColorBufferDMA_client_proc_t) getProc("rcCreateColorBufferDMA", userData);
return 0;
}
rcFlushWindowColorBufferAsync_client_proc_t rcFlushWindowColorBufferAsync;
rcDestroySyncKHR_client_proc_t rcDestroySyncKHR;
rcSetPuid_client_proc_t rcSetPuid;
- rcUpdateColorBufferDMA_client_proc_t rcUpdateColorBufferDMA;
- rcCreateColorBufferDMA_client_proc_t rcCreateColorBufferDMA;
virtual ~renderControl_client_context_t() {}
typedef renderControl_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
typedef void (renderControl_APIENTRY *rcFlushWindowColorBufferAsync_client_proc_t) (void * ctx, uint32_t);
typedef int (renderControl_APIENTRY *rcDestroySyncKHR_client_proc_t) (void * ctx, uint64_t);
typedef void (renderControl_APIENTRY *rcSetPuid_client_proc_t) (void * ctx, uint64_t);
-typedef int (renderControl_APIENTRY *rcUpdateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*, uint32_t);
-typedef uint32_t (renderControl_APIENTRY *rcCreateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, uint32_t, GLenum, int);
#endif
}
-int rcUpdateColorBufferDMA_enc(void *self , uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size)
-{
-
- renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
- IOStream *stream = ctx->m_stream;
- ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
- bool useChecksum = checksumCalculator->getVersion() > 0;
-
- const unsigned int __size_pixels = pixels_size;
- unsigned char *ptr;
- unsigned char *buf;
- const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 8 + 4 + 1*4;
- const size_t checksumSize = checksumCalculator->checksumByteSize();
- const size_t totalSize = sizeWithoutChecksum + checksumSize;
- buf = stream->alloc(totalSize);
- ptr = buf;
- int tmp = OP_rcUpdateColorBufferDMA;memcpy(ptr, &tmp, 4); ptr += 4;
- memcpy(ptr, &totalSize, 4); ptr += 4;
-
- memcpy(ptr, &colorbuffer, 4); ptr += 4;
- memcpy(ptr, &x, 4); ptr += 4;
- memcpy(ptr, &y, 4); ptr += 4;
- memcpy(ptr, &width, 4); ptr += 4;
- memcpy(ptr, &height, 4); ptr += 4;
- memcpy(ptr, &format, 4); ptr += 4;
- memcpy(ptr, &type, 4); ptr += 4;
- *(uint64_t *)(ptr) = ctx->lockAndWriteDma(pixels, __size_pixels); ptr += 8;
- memcpy(ptr, &pixels_size, 4); ptr += 4;
-
- if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
- if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
-
-
- int retval;
- stream->readback(&retval, 4);
- if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
- if (useChecksum) {
- unsigned char *checksumBufPtr = NULL;
- unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
- if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
- stream->readback(checksumBufPtr, checksumSize);
- if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
- ALOGE("rcUpdateColorBufferDMA: GL communication error, please report this issue to b.android.com.\n");
- abort();
- }
- }
- return retval;
-}
-
-uint32_t rcCreateColorBufferDMA_enc(void *self , uint32_t width, uint32_t height, GLenum internalFormat, int frameworkFormat)
-{
-
- renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
- IOStream *stream = ctx->m_stream;
- ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
- bool useChecksum = checksumCalculator->getVersion() > 0;
-
- unsigned char *ptr;
- unsigned char *buf;
- const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 4;
- const size_t checksumSize = checksumCalculator->checksumByteSize();
- const size_t totalSize = sizeWithoutChecksum + checksumSize;
- buf = stream->alloc(totalSize);
- ptr = buf;
- int tmp = OP_rcCreateColorBufferDMA;memcpy(ptr, &tmp, 4); ptr += 4;
- memcpy(ptr, &totalSize, 4); ptr += 4;
-
- memcpy(ptr, &width, 4); ptr += 4;
- memcpy(ptr, &height, 4); ptr += 4;
- memcpy(ptr, &internalFormat, 4); ptr += 4;
- memcpy(ptr, &frameworkFormat, 4); ptr += 4;
-
- if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
- if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
-
-
- uint32_t retval;
- stream->readback(&retval, 4);
- if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
- if (useChecksum) {
- unsigned char *checksumBufPtr = NULL;
- unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
- if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
- stream->readback(checksumBufPtr, checksumSize);
- if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
- ALOGE("rcCreateColorBufferDMA: GL communication error, please report this issue to b.android.com.\n");
- abort();
- }
- }
- return retval;
-}
-
} // namespace
renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
this->rcFlushWindowColorBufferAsync = &rcFlushWindowColorBufferAsync_enc;
this->rcDestroySyncKHR = &rcDestroySyncKHR_enc;
this->rcSetPuid = &rcSetPuid_enc;
- this->rcUpdateColorBufferDMA = &rcUpdateColorBufferDMA_enc;
- this->rcCreateColorBufferDMA = &rcCreateColorBufferDMA_enc;
}
ChecksumCalculator *m_checksumCalculator;
renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator);
- virtual uint64_t lockAndWriteDma(void* data, uint32_t sz) { return 0; }
};
#endif // GUARD_renderControl_encoder_context_t
\ No newline at end of file
void rcFlushWindowColorBufferAsync(uint32_t windowSurface);
int rcDestroySyncKHR(uint64_t sync);
void rcSetPuid(uint64_t puid);
- int rcUpdateColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size);
- uint32_t rcCreateColorBufferDMA(uint32_t width, uint32_t height, GLenum internalFormat, int frameworkFormat);
};
#endif
ctx->rcSetPuid(ctx, puid);
}
-int rcUpdateColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size)
-{
- GET_CONTEXT;
- return ctx->rcUpdateColorBufferDMA(ctx, colorbuffer, x, y, width, height, format, type, pixels, pixels_size);
-}
-
-uint32_t rcCreateColorBufferDMA(uint32_t width, uint32_t height, GLenum internalFormat, int frameworkFormat)
-{
- GET_CONTEXT;
- return ctx->rcCreateColorBufferDMA(ctx, width, height, internalFormat, frameworkFormat);
-}
-
{"rcFlushWindowColorBufferAsync", (void*)rcFlushWindowColorBufferAsync},
{"rcDestroySyncKHR", (void*)rcDestroySyncKHR},
{"rcSetPuid", (void*)rcSetPuid},
- {"rcUpdateColorBufferDMA", (void*)rcUpdateColorBufferDMA},
- {"rcCreateColorBufferDMA", (void*)rcCreateColorBufferDMA},
};
static const int renderControl_num_funcs = sizeof(renderControl_funcs_by_name) / sizeof(struct _renderControl_funcs_by_name);
#define OP_rcFlushWindowColorBufferAsync 10031
#define OP_rcDestroySyncKHR 10032
#define OP_rcSetPuid 10033
-#define OP_rcUpdateColorBufferDMA 10034
-#define OP_rcCreateColorBufferDMA 10035
-#define OP_last 10036
+#define OP_last 10034
#endif