Merge "[vulkan] Fix variable init on Fuchsia."
diff --git a/shared/OpenglCodecCommon/SocketStream.cpp b/shared/OpenglCodecCommon/SocketStream.cpp
index 067a75f..d6d31c0 100644
--- a/shared/OpenglCodecCommon/SocketStream.cpp
+++ b/shared/OpenglCodecCommon/SocketStream.cpp
@@ -132,7 +132,7 @@
const unsigned char *SocketStream::commitBufferAndReadFully(size_t size, void *buf, size_t len)
{
- return commitBuffer(size) ? nullptr : readFully(buf, len);
+ return commitBuffer(size) ? NULL : readFully(buf, len);
}
const unsigned char *SocketStream::read( void *buf, size_t *inout_len)
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index b2add4a..95b3e60 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -85,6 +85,12 @@
// Vulkan create resources with requirements
static const char kVulkanCreateResourcesWithRequirements[] = "ANDROID_EMU_vulkan_create_resources_with_requirements";
+// YUV420_888 to NV21
+static const char kYUV420888toNV21[] = "ANDROID_EMU_YUV420_888_to_NV21";
+
+// YUV host cache
+static const char kYUVCache[] = "ANDROID_EMU_YUV_Cache";
+
// Struct describing available emulator features
struct EmulatorFeatureInfo {
@@ -97,7 +103,9 @@
hasVulkan(false),
hasDeferredVulkanCommands(false),
hasVulkanNullOptionalStrings(false),
- hasVulkanCreateResourcesWithRequirements(false) { }
+ hasVulkanCreateResourcesWithRequirements(false),
+ hasYUV420888toNV21(false),
+ hasYUVCache (false) { }
SyncImpl syncImpl;
DmaImpl dmaImpl;
@@ -108,6 +116,8 @@
bool hasDeferredVulkanCommands;
bool hasVulkanNullOptionalStrings;
bool hasVulkanCreateResourcesWithRequirements;
+ bool hasYUV420888toNV21;
+ bool hasYUVCache;
};
#endif // __COMMON_EMULATOR_FEATURE_INFO_H
diff --git a/system/OpenglSystemCommon/FormatConversions.cpp b/system/OpenglSystemCommon/FormatConversions.cpp
index 92d7f0b..4b5c31c 100644
--- a/system/OpenglSystemCommon/FormatConversions.cpp
+++ b/system/OpenglSystemCommon/FormatConversions.cpp
@@ -55,9 +55,9 @@
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 uvStride = yStride;
uint32_t uvHeight = height / 2;
- uint32_t sz = yStride * height + 2 * (uvHeight * uvStride);
+ uint32_t sz = yStride * height + uvHeight * uvStride;
if (yStride_out) *yStride_out = yStride;
if (cStride_out) *cStride_out = uvStride;
@@ -218,6 +218,44 @@
}
}
}
+
+//HAL_PIXEL_FORMAT_YCbCr_420_888, or yuv420p is treated as NV21 across our
+//gralloc and camera module when feature YUV420888toNV21 enabled
+void rgb888_to_nv21(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom) {
+ const int rgb_stride = 3;
+
+ DD("%s convert %d by %d", __func__, width, height);
+ int yStride = width;
+ int cStride = yStride;
+ int yOffset = 0;
+
+ uint8_t *rgb_ptr0 = (uint8_t *)src;
+ uint8_t *nv21_y0 = (uint8_t *)dest;
+ uint8_t *nv21_v0 = nv21_y0 + yStride * height;
+
+ for (int j = top; j <= bottom; ++j) {
+ uint8_t *nv21_y = nv21_y0 + j * yStride;
+ uint8_t *nv21_v = nv21_v0 + (j/2) * cStride;
+ uint8_t *nv21_u = nv21_v + 1;
+ uint8_t *rgb_ptr = rgb_ptr0 + get_rgb_offset(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
+ nv21_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8);
+ bool ieven = (i & 1) == 0;
+ if (jeven && ieven) {
+ nv21_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
+ nv21_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,
@@ -305,8 +343,6 @@
}
}
-// 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) {
const int rgb_stride = 3;
@@ -350,6 +386,50 @@
}
}
+//HAL_PIXEL_FORMAT_YCbCr_420_888, or yuv420p is treated as NV21 across our
+//gralloc and camera module when feature YUV420888toNV21 enabled
+void nv21_to_rgb888(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom) {
+ const int rgb_stride = 3;
+
+ DD("%s convert %d by %d", __func__, width, height);
+ int yStride = width;
+ int cStride = yStride;
+ int yOffset = 0;
+
+ uint8_t *rgb_ptr0 = (uint8_t *)dest;
+ uint8_t *nv21_y0 = (uint8_t *)src;
+ uint8_t *nv21_v0 = nv21_y0 + yStride * height;
+
+ for (int j = top; j <= bottom; ++j) {
+ uint8_t *nv21_y = nv21_y0 + j * yStride;
+ uint8_t *nv21_v = nv21_v0 + (j/2) * cStride;
+ uint8_t *nv21_u = nv21_v + 1;
+ uint8_t *rgb_ptr = rgb_ptr0 + get_rgb_offset(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)nv21_y[i] - 16;
+ signed u = (signed)nv21_u[i / 2] - 128;
+ signed v = (signed)nv21_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_from_unlocked(
char* _dst, char* raw_data,
int unlockedWidth,
diff --git a/system/OpenglSystemCommon/FormatConversions.h b/system/OpenglSystemCommon/FormatConversions.h
index 6e15f36..196ca37 100644
--- a/system/OpenglSystemCommon/FormatConversions.h
+++ b/system/OpenglSystemCommon/FormatConversions.h
@@ -33,12 +33,16 @@
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 rgb888_to_nv21(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 nv21_to_rgb888(char* dest, char* src, int width, int height,
+ int left, int top, int right, int bottom);
void copy_rgb_buffer_from_unlocked(char* _dst, char* raw_data,
int unlockedWidth,
int width, int height, int top, int left,
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index cfe31b5..5e81ead 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -295,6 +295,8 @@
queryAndSetDeferredVulkanCommandsSupport(m_rcEnc);
queryAndSetVulkanNullOptionalStringsSupport(m_rcEnc);
queryAndSetVulkanCreateResourcesWithRequirementsSupport(m_rcEnc);
+ queryAndSetYUV420888toNV21(m_rcEnc);
+ queryAndSetYUVCache(m_rcEnc);
if (m_processPipe) {
m_processPipe->processPipeInit(m_rcEnc);
}
@@ -464,3 +466,17 @@
rcEnc->featureInfo()->hasVulkanCreateResourcesWithRequirements = true;
}
}
+
+void HostConnection::queryAndSetYUV420888toNV21(ExtendedRCEncoderContext* rcEnc) {
+ std::string glExtensions = queryGLExtensions(rcEnc);
+ if (glExtensions.find(kYUV420888toNV21) != std::string::npos) {
+ rcEnc->featureInfo()->hasYUV420888toNV21 = true;
+ }
+}
+
+void HostConnection::queryAndSetYUVCache(ExtendedRCEncoderContext* rcEnc) {
+ std::string glExtensions = queryGLExtensions(rcEnc);
+ if (glExtensions.find(kYUVCache) != std::string::npos) {
+ rcEnc->featureInfo()->hasYUVCache = true;
+ }
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index f79c11f..22b36b0 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -21,6 +21,7 @@
#include "renderControl_enc.h"
#include "ChecksumCalculator.h"
#include "goldfish_dma.h"
+#include "goldfish_address_space.h"
#include <cutils/native_handle.h>
@@ -47,7 +48,7 @@
public:
ExtendedRCEncoderContext(IOStream *stream, ChecksumCalculator *checksumCalculator)
: renderControl_encoder_context_t(stream, checksumCalculator),
- m_dmaCxt(NULL) { }
+ m_dmaCxt(NULL), m_addressSpaceBlock(NULL) { }
void setSyncImpl(SyncImpl syncImpl) { m_featureInfo.syncImpl = syncImpl; }
void setDmaImpl(DmaImpl dmaImpl) { m_featureInfo.dmaImpl = dmaImpl; }
void setHostComposition(HostComposition hostComposition) {
@@ -56,11 +57,20 @@
bool hasNativeSyncV3() const { return m_featureInfo.syncImpl >= SYNC_IMPL_NATIVE_SYNC_V3; }
bool hasHostCompositionV1() const {
return m_featureInfo.hostComposition == HOST_COMPOSITION_V1; }
+ bool hasYUV420toNV21() const {
+ return m_featureInfo.hasYUV420888toNV21; }
+ bool hasYUVCache() const {
+ return m_featureInfo.hasYUVCache; }
DmaImpl getDmaVersion() const { return m_featureInfo.dmaImpl; }
void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
+ void bindAddressSpaceBlock(GoldfishAddressSpaceBlock* block) {
+ m_addressSpaceBlock = block;
+ }
virtual uint64_t lockAndWriteDma(void* data, uint32_t size) {
- if (m_dmaCxt) {
- return lockAndWriteGoldfishDma(data, size, m_dmaCxt);
+ if (m_addressSpaceBlock) {
+ return writeAddressSpaceBlock(data, size, m_addressSpaceBlock);
+ } else if (m_dmaCxt) {
+ return writeGoldfishDma(data, size, m_dmaCxt);
} else {
ALOGE("%s: ERROR: No DMA context bound!", __func__);
return 0;
@@ -68,12 +78,20 @@
}
void setGLESMaxVersion(GLESMaxVersion ver) { m_featureInfo.glesMaxVersion = ver; }
GLESMaxVersion getGLESMaxVersion() const { return m_featureInfo.glesMaxVersion; }
+ bool hasDirectMem() const {
+#ifdef HOST_BUILD
+ // unit tests do not support restoring "guest" ram because there is no VM
+ return false;
+#else
+ return m_featureInfo.hasDirectMem;
+#endif
+ }
const EmulatorFeatureInfo* featureInfo_const() const { return &m_featureInfo; }
EmulatorFeatureInfo* featureInfo() { return &m_featureInfo; }
private:
- static uint64_t lockAndWriteGoldfishDma(void* data, uint32_t size,
- struct goldfish_dma_context* dmaCxt) {
+ static uint64_t writeGoldfishDma(void* data, uint32_t size,
+ struct goldfish_dma_context* dmaCxt) {
ALOGV("%s(data=%p, size=%u): call", __func__, data, size);
goldfish_dma_write(dmaCxt, data, size);
@@ -83,8 +101,20 @@
return paddr;
}
+ static uint64_t writeAddressSpaceBlock(void* data, uint32_t size,
+ GoldfishAddressSpaceBlock* block) {
+ ALOGV("%s(data=%p, size=%u): call", __func__, data, size);
+
+ memcpy(block->guestPtr(), data, size);
+ const uint64_t paddr = block->physAddr();
+
+ ALOGV("%s: paddr=0x%llx", __func__, (unsigned long long)paddr);
+ return paddr;
+ }
+
EmulatorFeatureInfo m_featureInfo;
struct goldfish_dma_context* m_dmaCxt;
+ GoldfishAddressSpaceBlock* m_addressSpaceBlock;
};
// Abstraction for gralloc handle conversion
@@ -168,6 +198,8 @@
void queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext *rcEnc);
void queryAndSetVulkanNullOptionalStringsSupport(ExtendedRCEncoderContext *rcEnc);
void queryAndSetVulkanCreateResourcesWithRequirementsSupport(ExtendedRCEncoderContext *rcEnc);
+ void queryAndSetYUV420888toNV21(ExtendedRCEncoderContext *mrcEnc);
+ void queryAndSetYUVCache(ExtendedRCEncoderContext *mrcEnc);
private:
IOStream *m_stream;
diff --git a/system/OpenglSystemCommon/VirtioGpuStream.h b/system/OpenglSystemCommon/VirtioGpuStream.h
index 5d44bcc..0be50e6 100644
--- a/system/OpenglSystemCommon/VirtioGpuStream.h
+++ b/system/OpenglSystemCommon/VirtioGpuStream.h
@@ -69,7 +69,7 @@
virtual int writeFully(const void *buf, size_t len);
virtual const unsigned char *readFully(void *buf, size_t len);
virtual int commitBuffer(size_t size);
- virtual int commitBufferAndReadFully(size_t size, void *buf, size_t len)
+ virtual const unsigned char* commitBufferAndReadFully(size_t size, void *buf, size_t len)
{
return commitBuffer(size) ? nullptr : readFully(buf, len);
}
diff --git a/system/gralloc/gralloc.cpp b/system/gralloc/gralloc.cpp
index 817107f..39e7e16 100644
--- a/system/gralloc/gralloc.cpp
+++ b/system/gralloc/gralloc.cpp
@@ -29,6 +29,7 @@
#endif
#include "goldfish_dma.h"
+#include "goldfish_address_space.h"
#include "FormatConversions.h"
#include "HostConnection.h"
#include "ProcessPipe.h"
@@ -125,13 +126,20 @@
#define INITIAL_DMA_REGION_SIZE 4096
struct gralloc_dmaregion_t {
gralloc_dmaregion_t(ExtendedRCEncoderContext *rcEnc)
- : sz(0), refcount(0), bigbufCount(0) {
+ : sz(INITIAL_DMA_REGION_SIZE), refcount(0), bigbufCount(0) {
+ memset(&goldfish_dma, 0, sizeof(goldfish_dma));
pthread_mutex_init(&lock, NULL);
- sz = INITIAL_DMA_REGION_SIZE;
- goldfish_dma_create_region(sz, &goldfish_dma);
+
+ if (rcEnc->hasDirectMem()) {
+ host_memory_allocator.hostMalloc(&address_space_block, sz);
+ } else if (rcEnc->getDmaVersion() > 0) {
+ goldfish_dma_create_region(sz, &goldfish_dma);
+ }
}
goldfish_dma_context goldfish_dma;
+ GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator;
+ GoldfishAddressSpaceBlock address_space_block;
uint32_t sz;
uint32_t refcount;
pthread_mutex_t lock;
@@ -149,6 +157,10 @@
return s_memregions;
}
+static bool has_DMA_support(const ExtendedRCEncoderContext *rcEnc) {
+ return rcEnc->getDmaVersion() > 0 || rcEnc->hasDirectMem();
+}
+
static gralloc_dmaregion_t* init_gralloc_dmaregion(ExtendedRCEncoderContext *rcEnc) {
D("%s: call\n", __func__);
if (!s_grdma) {
@@ -178,6 +190,15 @@
// max dma size: 2x 4K rgba8888
#define MAX_DMA_SIZE 66355200
+static bool put_gralloc_region_direct_mem_locked(gralloc_dmaregion_t* grdma, uint32_t sz) {
+ const bool shouldDelete = !grdma->refcount;
+ if (shouldDelete) {
+ grdma->host_memory_allocator.hostFree(&grdma->address_space_block);
+ }
+
+ return shouldDelete;
+}
+
static bool put_gralloc_region_dma_locked(gralloc_dmaregion_t* grdma, uint32_t sz) {
D("%s: call. refcount before: %u\n", __func__, grdma->refcount);
grdma->refcount--;
@@ -199,13 +220,29 @@
gralloc_dmaregion_t* grdma = init_gralloc_dmaregion(rcEnc);
pthread_mutex_lock(&grdma->lock);
- shouldDelete = put_gralloc_region_dma_locked(grdma, sz);
+ if (rcEnc->hasDirectMem()) {
+ shouldDelete = put_gralloc_region_direct_mem_locked(grdma, sz);
+ } else if (rcEnc->getDmaVersion() > 0) {
+ shouldDelete = put_gralloc_region_dma_locked(grdma, sz);
+ } else {
+ shouldDelete = false;
+ }
pthread_mutex_unlock(&grdma->lock);
return shouldDelete;
}
-static void gralloc_dmaregion_register_ashmem_dma(gralloc_dmaregion_t* grdma, uint32_t new_sz) {
+static void gralloc_dmaregion_register_ashmem_direct_mem_locked(gralloc_dmaregion_t* grdma, uint32_t new_sz) {
+ if (new_sz == grdma->sz) return;
+
+ GoldfishAddressSpaceHostMemoryAllocator* allocator = &grdma->host_memory_allocator;
+ GoldfishAddressSpaceBlock* block = &grdma->address_space_block;
+ allocator->hostFree(block);
+ allocator->hostMalloc(block, new_sz);
+ grdma->sz = new_sz;
+}
+
+static void gralloc_dmaregion_register_ashmem_dma_locked(gralloc_dmaregion_t* grdma, uint32_t new_sz) {
if (new_sz != grdma->sz) {
if (new_sz > MAX_DMA_SIZE) {
D("%s: requested sz %u too large (limit %u), set to fallback.",
@@ -227,7 +264,15 @@
pthread_mutex_lock(&grdma->lock);
D("%s: for sz %u, refcount %u", __func__, sz, grdma->refcount);
const uint32_t new_sz = std::max(grdma->sz, sz);
- gralloc_dmaregion_register_ashmem_dma(grdma, new_sz);
+
+ if (rcEnc->hasDirectMem()) {
+ gralloc_dmaregion_register_ashmem_direct_mem_locked(grdma, new_sz);
+ } else if (rcEnc->getDmaVersion() > 0) {
+ gralloc_dmaregion_register_ashmem_dma_locked(grdma, new_sz);
+ } else {
+ ALOGE("%s: unexpected DMA type", __func__);
+ }
+
pthread_mutex_unlock(&grdma->lock);
}
@@ -389,37 +434,40 @@
cb->frameworkFormat != HAL_PIXEL_FORMAT_YCbCr_420_888;
std::vector<char> convertedBuf;
- if ((doLocked && is_rgb_format) ||
- (!grdma && (doLocked || !is_rgb_format))) {
- convertedBuf.resize(rgbSz);
- to_send = &convertedBuf.front();
- send_buffer_size = rgbSz;
- }
if (doLocked && is_rgb_format) {
+ convertedBuf.resize(rgbSz);
+ to_send = &convertedBuf.front();
copy_rgb_buffer_from_unlocked(
to_send, pixels,
cb->width,
width, height, top, left, bpp);
}
- const bool hasDMA = rcEnc->getDmaVersion() > 0;
+ const bool hasDMA = has_DMA_support(rcEnc);
if (hasDMA && grdma->bigbufCount) {
D("%s: there are big buffers alive, use fallback (count %u)", __FUNCTION__,
grdma->bigbufCount);
}
if (hasDMA && !grdma->bigbufCount) {
- 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);
+ switch (cb->frameworkFormat) {
+ case HAL_PIXEL_FORMAT_YV12:
+ get_yv12_offsets(width, height, NULL, NULL, &send_buffer_size);
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ get_yuv420p_offsets(width, height, NULL, NULL, &send_buffer_size);
+ break;
}
- rcEnc->bindDmaContext(&grdma->goldfish_dma);
+ if (grdma->address_space_block.guestPtr()) {
+ rcEnc->bindAddressSpaceBlock(&grdma->address_space_block);
+ } else if (grdma->goldfish_dma.mapped_addr) {
+ rcEnc->bindDmaContext(&grdma->goldfish_dma);
+ } else {
+ ALOGE("%s: Unexpected DMA", __func__);
+ }
D("%s: call. dma update with sz=%u", __func__, send_buffer_size);
pthread_mutex_lock(&grdma->lock);
@@ -429,28 +477,33 @@
to_send, send_buffer_size);
pthread_mutex_unlock(&grdma->lock);
} else {
- char *tmpBuf = nullptr;
- if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
- tmpBuf = new char[cb->lockedWidth * cb->lockedHeight * bpp];
+ switch (cb->frameworkFormat) {
+ case HAL_PIXEL_FORMAT_YV12:
+ convertedBuf.resize(rgbSz);
+ to_send = &convertedBuf.front();
D("convert yv12 to rgb888 here");
- to_send = tmpBuf;
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) {
- tmpBuf = new char[cb->lockedWidth * cb->lockedHeight * bpp];
- to_send = tmpBuf;
- yuv420p_to_rgb888(to_send, pixels,
- width, height, left, top,
- left + width - 1, top + height - 1);
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ convertedBuf.resize(rgbSz);
+ to_send = &convertedBuf.front();
+ if (rcEnc->hasYUV420toNV21()) {
+ nv21_to_rgb888(to_send, pixels,
+ width, height, left, top,
+ left + width - 1, top + height - 1);
+ } else {
+ yuv420p_to_rgb888(to_send, pixels,
+ width, height, left, top,
+ left + width - 1, top + height - 1);
+ }
+ break;
}
rcEnc->rcUpdateColorBuffer(rcEnc, cb->hostHandle,
left, top, width, height,
cb->glFormat, cb->glType, to_send);
- if (tmpBuf != nullptr) {
- delete [] tmpBuf;
- }
}
}
@@ -747,6 +800,8 @@
cb->setFd(fd);
}
+ const bool hasDMA = has_DMA_support(rcEnc);
+
if (needHostCb) {
if (hostCon && rcEnc) {
GLenum allocFormat = glFormat;
@@ -759,9 +814,8 @@
allocFormat = GL_RGB;
}
- gralloc_dmaregion_t* grdma = init_gralloc_dmaregion(rcEnc);
hostCon->lock();
- if (rcEnc->getDmaVersion() > 0) {
+ if (hasDMA) {
cb->hostHandle = rcEnc->rcCreateColorBufferDMA(rcEnc, w, h, allocFormat, cb->emuFrameworkFormat);
} else {
cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, allocFormat);
@@ -773,7 +827,7 @@
// Could not create colorbuffer on host !!!
close(fd);
delete cb;
- ALOGD("%s: failed to create host cb! -EIO", __FUNCTION__);
+ ALOGE("%s: failed to create host cb! -EIO", __FUNCTION__);
return -EIO;
} else {
QEMU_PIPE_HANDLE refcountPipeFd = qemu_pipe_open("refcount");
@@ -807,7 +861,7 @@
}
hostCon->lock();
- if (rcEnc->getDmaVersion() > 0) {
+ if (hasDMA) {
get_gralloc_region(rcEnc); // map_buffer(cb, ...) refers here
}
hostCon->unlock();
@@ -1207,30 +1261,51 @@
// camera delivers bits to the buffer directly and does not require
// an explicit read, it also writes in YUV_420 (interleaved)
if (sw_read & !(usage & GRALLOC_USAGE_HW_CAMERA_MASK)) {
+ D("gralloc_lock read back color buffer %d %d ashmem base %p sz %d\n",
+ cb->width, cb->height, cb->ashmemBase, cb->ashmemSize);
void* rgb_addr = cpu_addr;
char* tmpBuf = 0;
if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12 ||
cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- // We are using RGB888
- tmpBuf = new char[cb->width * cb->height * 3];
- rgb_addr = tmpBuf;
- }
- D("gralloc_lock read back color buffer %d %d ashmem base %p sz %d\n",
- cb->width, cb->height, cb->ashmemBase, cb->ashmemSize);
- rcEnc->rcReadColorBuffer(rcEnc, cb->hostHandle,
- 0, 0, cb->width, cb->height, cb->glFormat, cb->glType, rgb_addr);
- if (tmpBuf) {
- if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
- D("convert rgb888 to yv12 here");
- rgb888_to_yv12((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
- } else if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- rgb888_to_yuv420p((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
+ if (rcEnc->hasYUVCache()) {
+ uint32_t buffer_size;
+ if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
+ get_yv12_offsets(cb->width, cb->height, NULL, NULL,
+ &buffer_size);
+ } else {
+ get_yuv420p_offsets(cb->width, cb->height, NULL, NULL,
+ &buffer_size);
+ }
+ D("read YUV copy from host");
+ rcEnc->rcReadColorBufferYUV(rcEnc, cb->hostHandle,
+ 0, 0, cb->width, cb->height,
+ rgb_addr, buffer_size);
+ } else {
+ // We are using RGB888
+ tmpBuf = new char[cb->width * cb->height * 3];
+ rcEnc->rcReadColorBuffer(rcEnc, cb->hostHandle,
+ 0, 0, cb->width, cb->height, cb->glFormat, cb->glType, tmpBuf);
+ if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
+ D("convert rgb888 to yv12 here");
+ rgb888_to_yv12((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
+ } else if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ if (rcEnc->hasYUV420toNV21()) {
+ D("convert rgb888 to nv21 here");
+ rgb888_to_nv21((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
+ } else {
+ D("convert rgb888 to yuv420p here");
+ rgb888_to_yuv420p((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
+ }
+ }
+ delete [] tmpBuf;
}
- delete [] tmpBuf;
+ } else {
+ rcEnc->rcReadColorBuffer(rcEnc, cb->hostHandle,
+ 0, 0, cb->width, cb->height, cb->glFormat, cb->glType, rgb_addr);
}
}
- if (rcEnc->getDmaVersion() > 0) {
+ if (has_DMA_support(rcEnc)) {
gralloc_dmaregion_register_ashmem(rcEnc, cb->ashmemSize);
}
hostCon->unlock();
@@ -1374,8 +1449,9 @@
uOffset = vOffset + cSize;
cStep = 1;
break;
- case HAL_PIXEL_FORMAT_YCbCr_420_888:
- if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_888: {
+ DEFINE_AND_VALIDATE_HOST_CONNECTION
+ if (rcEnc->hasYUV420toNV21()) {
yStride = cb->width;
cStride = cb->width;
yOffset = 0;
@@ -1383,14 +1459,24 @@
uOffset = vOffset + 1;
cStep = 2;
} else {
- yStride = cb->width;
- cStride = yStride / 2;
- yOffset = 0;
- uOffset = cb->height * yStride;
- vOffset = uOffset + cStride * cb->height / 2;
- cStep = 1;
+ if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
+ yStride = cb->width;
+ cStride = cb->width;
+ yOffset = 0;
+ vOffset = yStride * cb->height;
+ uOffset = vOffset + 1;
+ cStep = 2;
+ } else {
+ yStride = cb->width;
+ cStride = yStride / 2;
+ yOffset = 0;
+ uOffset = cb->height * yStride;
+ vOffset = uOffset + cStride * cb->height / 2;
+ cStep = 1;
+ }
}
break;
+ }
default:
ALOGE("gralloc_lock_ycbcr unexpected internal format %x",
cb->format);
diff --git a/system/renderControl_enc/renderControl_client_context.cpp b/system/renderControl_enc/renderControl_client_context.cpp
index 6da72fc..476d0da 100644
--- a/system/renderControl_enc/renderControl_client_context.cpp
+++ b/system/renderControl_enc/renderControl_client_context.cpp
@@ -56,6 +56,7 @@
rcGetDisplayPose = (rcGetDisplayPose_client_proc_t) getProc("rcGetDisplayPose", userData);
rcSetDisplayPose = (rcSetDisplayPose_client_proc_t) getProc("rcSetDisplayPose", userData);
rcSetColorBufferVulkanMode = (rcSetColorBufferVulkanMode_client_proc_t) getProc("rcSetColorBufferVulkanMode", userData);
+ rcReadColorBufferYUV = (rcReadColorBufferYUV_client_proc_t) getProc("rcReadColorBufferYUV", userData);
return 0;
}
diff --git a/system/renderControl_enc/renderControl_client_context.h b/system/renderControl_enc/renderControl_client_context.h
index d05fee1..8905afa 100644
--- a/system/renderControl_enc/renderControl_client_context.h
+++ b/system/renderControl_enc/renderControl_client_context.h
@@ -56,6 +56,7 @@
rcGetDisplayPose_client_proc_t rcGetDisplayPose;
rcSetDisplayPose_client_proc_t rcSetDisplayPose;
rcSetColorBufferVulkanMode_client_proc_t rcSetColorBufferVulkanMode;
+ rcReadColorBufferYUV_client_proc_t rcReadColorBufferYUV;
virtual ~renderControl_client_context_t() {}
typedef renderControl_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/renderControl_enc/renderControl_client_proc.h b/system/renderControl_enc/renderControl_client_proc.h
index f9690b6..6bba308 100644
--- a/system/renderControl_enc/renderControl_client_proc.h
+++ b/system/renderControl_enc/renderControl_client_proc.h
@@ -50,14 +50,15 @@
typedef uint32_t (renderControl_APIENTRY *rcCreateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, uint32_t, GLenum, int);
typedef void (renderControl_APIENTRY *rcWaitSyncKHR_client_proc_t) (void * ctx, uint64_t, EGLint);
typedef GLint (renderControl_APIENTRY *rcCompose_client_proc_t) (void * ctx, uint32_t, void*);
-typedef GLint (renderControl_APIENTRY *rcCreateDisplay_client_proc_t) (void * ctx, uint32_t*);
-typedef GLint (renderControl_APIENTRY *rcDestroyDisplay_client_proc_t) (void * ctx, uint32_t);
-typedef GLint (renderControl_APIENTRY *rcSetDisplayColorBuffer_client_proc_t) (void * ctx, uint32_t, uint32_t);
-typedef GLint (renderControl_APIENTRY *rcGetDisplayColorBuffer_client_proc_t) (void * ctx, uint32_t, uint32_t*);
-typedef GLint (renderControl_APIENTRY *rcGetColorBufferDisplay_client_proc_t) (void * ctx, uint32_t, uint32_t*);
-typedef GLint (renderControl_APIENTRY *rcGetDisplayPose_client_proc_t) (void * ctx, uint32_t, uint32_t*, uint32_t*, uint32_t*, uint32_t*);
-typedef GLint (renderControl_APIENTRY *rcSetDisplayPose_client_proc_t) (void * ctx, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+typedef int (renderControl_APIENTRY *rcCreateDisplay_client_proc_t) (void * ctx, uint32_t*);
+typedef int (renderControl_APIENTRY *rcDestroyDisplay_client_proc_t) (void * ctx, uint32_t);
+typedef int (renderControl_APIENTRY *rcSetDisplayColorBuffer_client_proc_t) (void * ctx, uint32_t, uint32_t);
+typedef int (renderControl_APIENTRY *rcGetDisplayColorBuffer_client_proc_t) (void * ctx, uint32_t, uint32_t*);
+typedef int (renderControl_APIENTRY *rcGetColorBufferDisplay_client_proc_t) (void * ctx, uint32_t, uint32_t*);
+typedef int (renderControl_APIENTRY *rcGetDisplayPose_client_proc_t) (void * ctx, uint32_t, GLint*, GLint*, uint32_t*, uint32_t*);
+typedef int (renderControl_APIENTRY *rcSetDisplayPose_client_proc_t) (void * ctx, uint32_t, GLint, GLint, uint32_t, uint32_t);
typedef GLint (renderControl_APIENTRY *rcSetColorBufferVulkanMode_client_proc_t) (void * ctx, uint32_t, uint32_t);
+typedef void (renderControl_APIENTRY *rcReadColorBufferYUV_client_proc_t) (void * ctx, uint32_t, GLint, GLint, GLint, GLint, void*, uint32_t);
#endif
diff --git a/system/renderControl_enc/renderControl_enc.cpp b/system/renderControl_enc/renderControl_enc.cpp
index a2d765f..fab8a15 100644
--- a/system/renderControl_enc/renderControl_enc.cpp
+++ b/system/renderControl_enc/renderControl_enc.cpp
@@ -1436,7 +1436,7 @@
return retval;
}
-GLint rcCreateDisplay_enc(void *self , uint32_t* displayId)
+int rcCreateDisplay_enc(void *self , uint32_t* displayId)
{
renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
@@ -1463,7 +1463,7 @@
stream->readback(displayId, __size_displayId);
if (useChecksum) checksumCalculator->addBuffer(displayId, __size_displayId);
- GLint retval;
+ int retval;
stream->readback(&retval, 4);
if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
if (useChecksum) {
@@ -1479,7 +1479,7 @@
return retval;
}
-GLint rcDestroyDisplay_enc(void *self , uint32_t displayId)
+int rcDestroyDisplay_enc(void *self , uint32_t displayId)
{
renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
@@ -1503,7 +1503,7 @@
if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
- GLint retval;
+ int retval;
stream->readback(&retval, 4);
if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
if (useChecksum) {
@@ -1519,7 +1519,7 @@
return retval;
}
-GLint rcSetDisplayColorBuffer_enc(void *self , uint32_t displayId, uint32_t colorBuffer)
+int rcSetDisplayColorBuffer_enc(void *self , uint32_t displayId, uint32_t colorBuffer)
{
renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
@@ -1544,7 +1544,7 @@
if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
- GLint retval;
+ int retval;
stream->readback(&retval, 4);
if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
if (useChecksum) {
@@ -1560,7 +1560,7 @@
return retval;
}
-GLint rcGetDisplayColorBuffer_enc(void *self , uint32_t displayId, uint32_t* colorBuffer)
+int rcGetDisplayColorBuffer_enc(void *self , uint32_t displayId, uint32_t* colorBuffer)
{
renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
@@ -1588,7 +1588,7 @@
stream->readback(colorBuffer, __size_colorBuffer);
if (useChecksum) checksumCalculator->addBuffer(colorBuffer, __size_colorBuffer);
- GLint retval;
+ int retval;
stream->readback(&retval, 4);
if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
if (useChecksum) {
@@ -1604,7 +1604,7 @@
return retval;
}
-GLint rcGetColorBufferDisplay_enc(void *self , uint32_t colorBuffer, uint32_t* displayId)
+int rcGetColorBufferDisplay_enc(void *self , uint32_t colorBuffer, uint32_t* displayId)
{
renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
@@ -1632,7 +1632,7 @@
stream->readback(displayId, __size_displayId);
if (useChecksum) checksumCalculator->addBuffer(displayId, __size_displayId);
- GLint retval;
+ int retval;
stream->readback(&retval, 4);
if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
if (useChecksum) {
@@ -1648,7 +1648,7 @@
return retval;
}
-GLint rcGetDisplayPose_enc(void *self , uint32_t displayId, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
+int rcGetDisplayPose_enc(void *self , uint32_t displayId, GLint* x, GLint* y, uint32_t* w, uint32_t* h)
{
renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
@@ -1688,7 +1688,7 @@
stream->readback(h, __size_h);
if (useChecksum) checksumCalculator->addBuffer(h, __size_h);
- GLint retval;
+ int retval;
stream->readback(&retval, 4);
if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
if (useChecksum) {
@@ -1704,7 +1704,7 @@
return retval;
}
-GLint rcSetDisplayPose_enc(void *self , uint32_t displayId, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+int rcSetDisplayPose_enc(void *self , uint32_t displayId, GLint x, GLint y, uint32_t w, uint32_t h)
{
renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
@@ -1732,7 +1732,7 @@
if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
- GLint retval;
+ int retval;
stream->readback(&retval, 4);
if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
if (useChecksum) {
@@ -1789,6 +1789,50 @@
return retval;
}
+void rcReadColorBufferYUV_enc(void *self , uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, 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 + 0 + 4 + 1*4;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(totalSize);
+ ptr = buf;
+ int tmp = OP_rcReadColorBufferYUV;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;
+ *(unsigned int *)(ptr) = __size_pixels; ptr += 4;
+ memcpy(ptr, &pixels_size, 4); ptr += 4;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+ stream->readback(pixels, __size_pixels);
+ if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
+ 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("rcReadColorBufferYUV: GL communication error, please report this issue to b.android.com.\n");
+ abort();
+ }
+ }
+}
+
} // namespace
renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -1842,5 +1886,6 @@
this->rcGetDisplayPose = &rcGetDisplayPose_enc;
this->rcSetDisplayPose = &rcSetDisplayPose_enc;
this->rcSetColorBufferVulkanMode = &rcSetColorBufferVulkanMode_enc;
+ this->rcReadColorBufferYUV = &rcReadColorBufferYUV_enc;
}
diff --git a/system/renderControl_enc/renderControl_entry.cpp b/system/renderControl_enc/renderControl_entry.cpp
index 1314c7d..0974a96 100644
--- a/system/renderControl_enc/renderControl_entry.cpp
+++ b/system/renderControl_enc/renderControl_entry.cpp
@@ -43,14 +43,15 @@
uint32_t rcCreateColorBufferDMA(uint32_t width, uint32_t height, GLenum internalFormat, int frameworkFormat);
void rcWaitSyncKHR(uint64_t sync, EGLint flags);
GLint rcCompose(uint32_t bufferSize, void* buffer);
- GLint rcCreateDisplay(uint32_t* displayId);
- GLint rcDestroyDisplay(uint32_t displayId);
- GLint rcSetDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer);
- GLint rcGetDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer);
- GLint rcGetColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId);
- GLint rcGetDisplayPose(uint32_t displayId, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h);
- GLint rcSetDisplayPose(uint32_t displayId, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+ int rcCreateDisplay(uint32_t* displayId);
+ int rcDestroyDisplay(uint32_t displayId);
+ int rcSetDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer);
+ int rcGetDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer);
+ int rcGetColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId);
+ int rcGetDisplayPose(uint32_t displayId, GLint* x, GLint* y, uint32_t* w, uint32_t* h);
+ int rcSetDisplayPose(uint32_t displayId, GLint x, GLint y, uint32_t w, uint32_t h);
GLint rcSetColorBufferVulkanMode(uint32_t colorBuffer, uint32_t mode);
+ void rcReadColorBufferYUV(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, void* pixels, uint32_t pixels_size);
};
#ifndef GET_CONTEXT
@@ -287,43 +288,43 @@
return ctx->rcCompose(ctx, bufferSize, buffer);
}
-GLint rcCreateDisplay(uint32_t* displayId)
+int rcCreateDisplay(uint32_t* displayId)
{
GET_CONTEXT;
return ctx->rcCreateDisplay(ctx, displayId);
}
-GLint rcDestroyDisplay(uint32_t displayId)
+int rcDestroyDisplay(uint32_t displayId)
{
GET_CONTEXT;
return ctx->rcDestroyDisplay(ctx, displayId);
}
-GLint rcSetDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer)
+int rcSetDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer)
{
GET_CONTEXT;
return ctx->rcSetDisplayColorBuffer(ctx, displayId, colorBuffer);
}
-GLint rcGetDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer)
+int rcGetDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer)
{
GET_CONTEXT;
return ctx->rcGetDisplayColorBuffer(ctx, displayId, colorBuffer);
}
-GLint rcGetColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId)
+int rcGetColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId)
{
GET_CONTEXT;
return ctx->rcGetColorBufferDisplay(ctx, colorBuffer, displayId);
}
-GLint rcGetDisplayPose(uint32_t displayId, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
+int rcGetDisplayPose(uint32_t displayId, GLint* x, GLint* y, uint32_t* w, uint32_t* h)
{
GET_CONTEXT;
return ctx->rcGetDisplayPose(ctx, displayId, x, y, w, h);
}
-GLint rcSetDisplayPose(uint32_t displayId, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+int rcSetDisplayPose(uint32_t displayId, GLint x, GLint y, uint32_t w, uint32_t h)
{
GET_CONTEXT;
return ctx->rcSetDisplayPose(ctx, displayId, x, y, w, h);
@@ -335,3 +336,9 @@
return ctx->rcSetColorBufferVulkanMode(ctx, colorBuffer, mode);
}
+void rcReadColorBufferYUV(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, void* pixels, uint32_t pixels_size)
+{
+ GET_CONTEXT;
+ ctx->rcReadColorBufferYUV(ctx, colorbuffer, x, y, width, height, pixels, pixels_size);
+}
+
diff --git a/system/renderControl_enc/renderControl_ftable.h b/system/renderControl_enc/renderControl_ftable.h
index 035dfac..da58a04 100644
--- a/system/renderControl_enc/renderControl_ftable.h
+++ b/system/renderControl_enc/renderControl_ftable.h
@@ -54,6 +54,7 @@
{"rcGetDisplayPose", (void*)rcGetDisplayPose},
{"rcSetDisplayPose", (void*)rcSetDisplayPose},
{"rcSetColorBufferVulkanMode", (void*)rcSetColorBufferVulkanMode},
+ {"rcReadColorBufferYUV", (void*)rcReadColorBufferYUV},
};
static const int renderControl_num_funcs = sizeof(renderControl_funcs_by_name) / sizeof(struct _renderControl_funcs_by_name);
diff --git a/system/renderControl_enc/renderControl_opcodes.h b/system/renderControl_enc/renderControl_opcodes.h
index d2927d2..2c3780b 100644
--- a/system/renderControl_enc/renderControl_opcodes.h
+++ b/system/renderControl_enc/renderControl_opcodes.h
@@ -49,7 +49,8 @@
#define OP_rcGetDisplayPose 10043
#define OP_rcSetDisplayPose 10044
#define OP_rcSetColorBufferVulkanMode 10045
-#define OP_last 10046
+#define OP_rcReadColorBufferYUV 10046
+#define OP_last 10047
#endif