Reland: Support host decoding with update_color_buffer on minigbm
minigbm creates an NV12 image when the guest wanted yuv_420_888. our
host decoder outputs yuv_420_888, but this isn't compatible with nv21,
and resulted in garbled images when fed to YUVConverter.
but gfxstream never created a yuv_420_888 gpu image on the host anyway. All
we need to do is explicitly tell YUVConverter to convert from yuv_420_888.
Bug: 162770284
Change-Id: I3788183e7c94adfd0d52caafbbe67a1ed0d23c77
diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp
index 095c487..2824185 100644
--- a/stream-servers/FrameBuffer.cpp
+++ b/stream-servers/FrameBuffer.cpp
@@ -2197,6 +2197,28 @@
return true;
}
+bool FrameBuffer::updateColorBufferFromFrameworkFormat(HandleType p_colorbuffer, int x, int y,
+ int width, int height,
+ FrameworkFormat fwkFormat, GLenum format,
+ GLenum type, void* pixels) {
+ if (width == 0 || height == 0) {
+ return false;
+ }
+
+ AutoLock mutex(m_lock);
+
+ ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
+ if (c == m_colorbuffers.end()) {
+ // bad colorbuffer handle
+ return false;
+ }
+
+ (*c).second.cb->subUpdateFromFrameworkFormat(x, y, width, height, fwkFormat, format, type,
+ pixels);
+
+ return true;
+}
+
bool FrameBuffer::replaceColorBufferContents(
HandleType p_colorbuffer, const void* pixels, size_t numBytes) {
AutoLock mutex(m_lock);
diff --git a/stream-servers/FrameBuffer.h b/stream-servers/FrameBuffer.h
index ceb785b..e190a75 100644
--- a/stream-servers/FrameBuffer.h
+++ b/stream-servers/FrameBuffer.h
@@ -406,6 +406,9 @@
bool updateColorBuffer(HandleType p_colorbuffer, int x, int y, int width,
int height, GLenum format, GLenum type,
void* pixels);
+ bool updateColorBufferFromFrameworkFormat(HandleType p_colorbuffer, int x, int y, int width,
+ int height, FrameworkFormat fwkFormat, GLenum format,
+ GLenum type, void* pixels);
// Replaces contents completely using the color buffer's current format,
// with row length equal to width of a row in bytes.
// The number of bytes is passed as a check.
diff --git a/stream-servers/RendererImpl.cpp b/stream-servers/RendererImpl.cpp
index 9916eea..7c3dbf9 100644
--- a/stream-servers/RendererImpl.cpp
+++ b/stream-servers/RendererImpl.cpp
@@ -523,170 +523,118 @@
}
static struct AndroidVirtioGpuOps sVirtioGpuOps = {
- .create_buffer_with_handle =
- [](uint64_t size, uint32_t handle) {
- FrameBuffer::getFB()->createBufferWithHandle(size, handle);
- },
- .create_color_buffer_with_handle =
- [](uint32_t width,
- uint32_t height,
- uint32_t format,
- uint32_t fwkFormat,
- uint32_t handle) {
- FrameBuffer::getFB()->createColorBufferWithHandle(
- width, height, (GLenum)format,
- (FrameworkFormat)fwkFormat, handle);
- },
- .open_color_buffer =
- [](uint32_t handle) {
- FrameBuffer::getFB()->openColorBuffer(handle);
- },
- .close_buffer =
- [](uint32_t handle) {
- FrameBuffer::getFB()->closeBuffer(handle);
- },
- .close_color_buffer =
- [](uint32_t handle) {
- FrameBuffer::getFB()->closeColorBuffer(handle);
- },
- .update_buffer =
- [](uint32_t handle,
- uint64_t offset,
- uint64_t size,
- void* bytes) {
- FrameBuffer::getFB()->updateBuffer(
- handle, offset, size, bytes);
- },
- .update_color_buffer =
- [](uint32_t handle,
- int x,
- int y,
- int width,
- int height,
- uint32_t format,
- uint32_t type,
- void* pixels) {
- FrameBuffer::getFB()->updateColorBuffer(
- handle, x, y, width, height, format, type, pixels);
- },
- .read_buffer =
- [](uint32_t handle,
- uint64_t offset,
- uint64_t size,
- void* bytes) {
- FrameBuffer::getFB()->readBuffer(
- handle, offset, size, bytes);
- },
- .read_color_buffer =
- [](uint32_t handle,
- int x,
- int y,
- int width,
- int height,
- uint32_t format,
- uint32_t type,
- void* pixels) {
- FrameBuffer::getFB()->readColorBuffer(
- handle, x, y, width, height, format, type, pixels);
- },
- .read_color_buffer_yuv =
- [](uint32_t handle,
- int x,
- int y,
- int width,
- int height,
- void* pixels,
- uint32_t pixels_size) {
- FrameBuffer::getFB()->readColorBufferYUV(
- handle, x, y, width, height, pixels, pixels_size);
- },
- .post_color_buffer =
- [](uint32_t handle) { FrameBuffer::getFB()->post(handle); },
- .async_post_color_buffer =
- [](uint32_t handle, CpuCompletionCallback cb) {
- FrameBuffer::getFB()->postWithCallback(handle, cb); },
- .repost = []() { FrameBuffer::getFB()->repost(); },
- .create_yuv_textures =
- [](uint32_t type,
- uint32_t count,
- int width,
- int height,
- uint32_t* output) {
- FrameBuffer::getFB()->createYUVTextures(type, count, width,
- height, output);
- },
- .destroy_yuv_textures =
- [](uint32_t type, uint32_t count, uint32_t* textures) {
- FrameBuffer::getFB()->destroyYUVTextures(type, count,
- textures);
- },
- .update_yuv_textures =
- [](uint32_t type,
- uint32_t* textures,
- void* privData,
- void* func) {
- FrameBuffer::getFB()->updateYUVTextures(type, textures,
- privData, func);
- },
- .swap_textures_and_update_color_buffer =
- [](uint32_t colorbufferhandle,
- int x,
- int y,
- int width,
- int height,
- uint32_t format,
- uint32_t type,
- uint32_t texture_type,
- uint32_t* textures,
- void* metadata) {
- (void)metadata;
- // TODO(joshuaduong): CP go/oag/2170490
- FrameBuffer::getFB()->swapTexturesAndUpdateColorBuffer(
- colorbufferhandle, x, y, width, height, format,
- type, texture_type, textures);
- },
- .get_last_posted_color_buffer = []() {
- return FrameBuffer::getFB()->getLastPostedColorBuffer();
+ .create_buffer_with_handle =
+ [](uint64_t size, uint32_t handle) {
+ FrameBuffer::getFB()->createBufferWithHandle(size, handle);
},
- .bind_color_buffer_to_texture = [](uint32_t handle) {
- FrameBuffer::getFB()->bindColorBufferToTexture2(handle);
+ .create_color_buffer_with_handle =
+ [](uint32_t width, uint32_t height, uint32_t format, uint32_t fwkFormat, uint32_t handle) {
+ FrameBuffer::getFB()->createColorBufferWithHandle(width, height, (GLenum)format,
+ (FrameworkFormat)fwkFormat, handle);
},
- .get_global_egl_context = []() {
- return FrameBuffer::getFB()->getGlobalEGLContext();
+ .open_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->openColorBuffer(handle); },
+ .close_buffer = [](uint32_t handle) { FrameBuffer::getFB()->closeBuffer(handle); },
+ .close_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->closeColorBuffer(handle); },
+ .update_buffer =
+ [](uint32_t handle, uint64_t offset, uint64_t size, void* bytes) {
+ FrameBuffer::getFB()->updateBuffer(handle, offset, size, bytes);
},
- .wait_for_gpu = [](uint64_t eglsync) {
- FrameBuffer::getFB()->waitForGpu(eglsync);
+ .update_color_buffer =
+ [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
+ void* pixels) {
+ FrameBuffer::getFB()->updateColorBuffer(handle, x, y, width, height, format, type,
+ pixels);
},
- .wait_for_gpu_vulkan = [](uint64_t device, uint64_t fence) {
+ .read_buffer =
+ [](uint32_t handle, uint64_t offset, uint64_t size, void* bytes) {
+ FrameBuffer::getFB()->readBuffer(handle, offset, size, bytes);
+ },
+ .read_color_buffer =
+ [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
+ void* pixels) {
+ FrameBuffer::getFB()->readColorBuffer(handle, x, y, width, height, format, type,
+ pixels);
+ },
+ .read_color_buffer_yuv =
+ [](uint32_t handle, int x, int y, int width, int height, void* pixels,
+ uint32_t pixels_size) {
+ FrameBuffer::getFB()->readColorBufferYUV(handle, x, y, width, height, pixels,
+ pixels_size);
+ },
+ .post_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->post(handle); },
+ .async_post_color_buffer =
+ [](uint32_t handle, CpuCompletionCallback cb) {
+ FrameBuffer::getFB()->postWithCallback(handle, cb);
+ },
+ .repost = []() { FrameBuffer::getFB()->repost(); },
+ .create_yuv_textures =
+ [](uint32_t type, uint32_t count, int width, int height, uint32_t* output) {
+ FrameBuffer::getFB()->createYUVTextures(type, count, width, height, output);
+ },
+ .destroy_yuv_textures =
+ [](uint32_t type, uint32_t count, uint32_t* textures) {
+ FrameBuffer::getFB()->destroyYUVTextures(type, count, textures);
+ },
+ .update_yuv_textures =
+ [](uint32_t type, uint32_t* textures, void* privData, void* func) {
+ FrameBuffer::getFB()->updateYUVTextures(type, textures, privData, func);
+ },
+ .swap_textures_and_update_color_buffer =
+ [](uint32_t colorbufferhandle, int x, int y, int width, int height, uint32_t format,
+ uint32_t type, uint32_t texture_type, uint32_t* textures, void* metadata) {
+ (void)metadata;
+ // TODO(joshuaduong): CP go/oag/2170490
+ FrameBuffer::getFB()->swapTexturesAndUpdateColorBuffer(
+ colorbufferhandle, x, y, width, height, format, type, texture_type, textures);
+ },
+ .get_last_posted_color_buffer =
+ []() { return FrameBuffer::getFB()->getLastPostedColorBuffer(); },
+ .bind_color_buffer_to_texture =
+ [](uint32_t handle) { FrameBuffer::getFB()->bindColorBufferToTexture2(handle); },
+ .get_global_egl_context = []() { return FrameBuffer::getFB()->getGlobalEGLContext(); },
+ .wait_for_gpu = [](uint64_t eglsync) { FrameBuffer::getFB()->waitForGpu(eglsync); },
+ .wait_for_gpu_vulkan =
+ [](uint64_t device, uint64_t fence) {
FrameBuffer::getFB()->waitForGpuVulkan(device, fence);
},
- .set_guest_managed_color_buffer_lifetime = [](bool guestManaged) {
+ .set_guest_managed_color_buffer_lifetime =
+ [](bool guestManaged) {
FrameBuffer::getFB()->setGuestManagedColorBufferLifetime(guestManaged);
},
- .async_wait_for_gpu_with_cb = [](uint64_t eglsync, FenceCompletionCallback cb) {
+ .async_wait_for_gpu_with_cb =
+ [](uint64_t eglsync, FenceCompletionCallback cb) {
FrameBuffer::getFB()->asyncWaitForGpuWithCb(eglsync, cb);
},
- .async_wait_for_gpu_vulkan_with_cb = [](uint64_t device, uint64_t fence, FenceCompletionCallback cb) {
+ .async_wait_for_gpu_vulkan_with_cb =
+ [](uint64_t device, uint64_t fence, FenceCompletionCallback cb) {
FrameBuffer::getFB()->asyncWaitForGpuVulkanWithCb(device, fence, cb);
},
- .async_wait_for_gpu_vulkan_qsri_with_cb = [](uint64_t image, FenceCompletionCallback cb) {
+ .async_wait_for_gpu_vulkan_qsri_with_cb =
+ [](uint64_t image, FenceCompletionCallback cb) {
FrameBuffer::getFB()->asyncWaitForGpuVulkanQsriWithCb(image, cb);
},
- .wait_for_gpu_vulkan_qsri = [](uint64_t image) {
- FrameBuffer::getFB()->waitForGpuVulkanQsri(image);
- },
- .platform_import_resource = [](uint32_t handle, uint32_t info, void* resource) {
+ .wait_for_gpu_vulkan_qsri =
+ [](uint64_t image) { FrameBuffer::getFB()->waitForGpuVulkanQsri(image); },
+ .platform_import_resource =
+ [](uint32_t handle, uint32_t info, void* resource) {
return FrameBuffer::getFB()->platformImportResource(handle, info, resource);
},
- .platform_resource_info = [](uint32_t handle, int32_t* width, int32_t* height, int32_t* internal_format) {
+ .platform_resource_info =
+ [](uint32_t handle, int32_t* width, int32_t* height, int32_t* internal_format) {
return FrameBuffer::getFB()->getColorBufferInfo(handle, width, height, internal_format);
},
- .platform_create_shared_egl_context = []() {
- return FrameBuffer::getFB()->platformCreateSharedEglContext();
- },
- .platform_destroy_shared_egl_context = [](void* context) {
+ .platform_create_shared_egl_context =
+ []() { return FrameBuffer::getFB()->platformCreateSharedEglContext(); },
+ .platform_destroy_shared_egl_context =
+ [](void* context) {
return FrameBuffer::getFB()->platformDestroySharedEglContext(context);
},
+ .update_color_buffer_from_framework_format =
+ [](uint32_t handle, int x, int y, int width, int height, uint32_t fwkFormat,
+ uint32_t format, uint32_t type, void* pixels, void* pMetadata) {
+ FrameBuffer::getFB()->updateColorBufferFromFrameworkFormat(
+ handle, x, y, width, height, (FrameworkFormat)fwkFormat, format, type, pixels);
+ },
};
struct AndroidVirtioGpuOps* RendererImpl::getVirtioGpuOps() {
diff --git a/stream-servers/gl/ColorBufferGl.cpp b/stream-servers/gl/ColorBufferGl.cpp
index b6adab0..10625be 100644
--- a/stream-servers/gl/ColorBufferGl.cpp
+++ b/stream-servers/gl/ColorBufferGl.cpp
@@ -584,7 +584,12 @@
if (m_vulkanOnly) {
return;
}
+ subUpdateFromFrameworkFormat(x, y, width, height, m_frameworkFormat, p_format, p_type, pixels);
+}
+void ColorBuffer::subUpdateFromFrameworkFormat(int x, int y, int width, int height,
+ FrameworkFormat fwkFormat, GLenum p_format,
+ GLenum p_type, void* pixels) {
const GLenum p_unsizedFormat = sGetUnsizedColorBufferFormat(p_format);
RecursiveScopedContextBind context(m_helper);
if (!context.isOk()) {
@@ -602,13 +607,13 @@
m_needFormatCheck = false;
}
- if (m_frameworkFormat != FRAMEWORK_FORMAT_GL_COMPATIBLE) {
+ if (m_frameworkFormat != FRAMEWORK_FORMAT_GL_COMPATIBLE || fwkFormat != m_frameworkFormat) {
assert(m_yuv_converter.get());
// This FBO will convert the YUV frame to RGB
// and render it to |m_tex|.
bindFbo(&m_yuv_conversion_fbo, m_tex, m_needFboReattach);
- m_yuv_converter->drawConvert(x, y, width, height, (char*)pixels);
+ m_yuv_converter->drawConvertFromFormat(fwkFormat, x, y, width, height, (char*)pixels);
unbindFbo();
// |m_tex| still needs to be bound afterwards
diff --git a/stream-servers/gl/ColorBufferGl.h b/stream-servers/gl/ColorBufferGl.h
index 800059a..6add3d5 100644
--- a/stream-servers/gl/ColorBufferGl.h
+++ b/stream-servers/gl/ColorBufferGl.h
@@ -150,6 +150,9 @@
GLenum p_format,
GLenum p_type,
void* pixels);
+ void subUpdateFromFrameworkFormat(int x, int y, int width, int height,
+ FrameworkFormat fwkFormat, GLenum p_format, GLenum p_type,
+ void* pixels);
// Completely replaces contents, assuming that |pixels| is a buffer
// that is allocated and filled with the same format.
diff --git a/stream-servers/gl/YUVConverter.cpp b/stream-servers/gl/YUVConverter.cpp
index 36aac25..1f0732e 100644
--- a/stream-servers/gl/YUVConverter.cpp
+++ b/stream-servers/gl/YUVConverter.cpp
@@ -880,17 +880,35 @@
}
mFormat = format;
+ mTexturesSwapped = true;
}
+// drawConvert: per-frame updates.
+// Update YUV textures, then draw the fullscreen
+// quad set up above, which results in a framebuffer
+// with the RGB colors.
void YUVConverter::drawConvert(int x, int y, int width, int height, const char* pixels) {
- YUV_DEBUG_LOG("x:%d y:%d w:%d h:%d", x, y, width, height);
+ drawConvertFromFormat(mFormat, x, y, width, height, pixels);
+}
+void YUVConverter::drawConvertFromFormat(FrameworkFormat format, int x, int y, int width,
+ int height, const char* pixels) {
saveGLState();
if (pixels && (width != mWidth || height != mHeight)) {
reset();
}
- if (mProgram == 0) {
+ bool uploadFormatChanged = !mTexturesSwapped && pixels && (format != mFormat);
+ bool initNeeded = (mProgram == 0) || uploadFormatChanged;
+
+ if (initNeeded) {
+ if (uploadFormatChanged) {
+ mFormat = format;
+ // TODO: missing cherry-picks, put it back
+ // b/264928117
+ //mCbFormat = format;
+ reset();
+ }
init(width, height, mFormat);
}
diff --git a/stream-servers/gl/YUVConverter.h b/stream-servers/gl/YUVConverter.h
index eebeb4c..8cddee1 100644
--- a/stream-servers/gl/YUVConverter.h
+++ b/stream-servers/gl/YUVConverter.h
@@ -63,6 +63,8 @@
// the host color buffer
// (rcUpdateColorBuffer)
void drawConvert(int x, int y, int width, int height, const char* pixels);
+ void drawConvertFromFormat(FrameworkFormat format, int x, int y, int width, int height,
+ const char* pixels);
uint32_t getDataSize();
// read YUV data into pixels, exactly pixels_size bytes;
@@ -101,6 +103,7 @@
GLuint mTextureY = 0;
GLuint mTextureU = 0;
GLuint mTextureV = 0;
+ bool mTexturesSwapped = false;
GLint mUniformLocYWidthCutoff = -1;
GLint mUniformLocUVWidthCutoff = -1;
GLint mUniformLocSamplerY = -1;