summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Macnak <natsu@google.com>2022-04-05 19:49:09 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-04-05 19:49:09 +0000
commit402f8c09706ac0b48d64394379f0de2b6f6b6ed9 (patch)
treed0d3a07b49b174d5e921dc64b80e9a42a9067b5d
parent15e2bf44a6ed5dbb005592fe650dc0b8c915863b (diff)
parent3034307a5bedbe5934eb1ae47688a513f962e909 (diff)
downloadvulkan-cereal-402f8c09706ac0b48d64394379f0de2b6f6b6ed9.tar.gz
Merge "Adds P010 support" am: 3034307a5b
Original change: https://android-review.googlesource.com/c/device/generic/vulkan-cereal/+/2050572 Change-Id: I755f7341ffee54afe88f1e65175d7d432a3f024d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--stream-servers/ColorBuffer.cpp1
-rw-r--r--stream-servers/FrameworkFormats.h1
-rw-r--r--stream-servers/YUVConverter.cpp236
-rw-r--r--stream-servers/YUVConverter.h9
-rw-r--r--stream-servers/virtio-gpu-gfxstream-renderer.cpp14
5 files changed, 176 insertions, 85 deletions
diff --git a/stream-servers/ColorBuffer.cpp b/stream-servers/ColorBuffer.cpp
index 11ba8221..fb2209dd 100644
--- a/stream-servers/ColorBuffer.cpp
+++ b/stream-servers/ColorBuffer.cpp
@@ -960,6 +960,7 @@ void ColorBuffer::restore() {
switch (m_frameworkFormat) {
case FRAMEWORK_FORMAT_GL_COMPATIBLE:
break;
+ case FRAMEWORK_FORMAT_P010:
case FRAMEWORK_FORMAT_YV12:
case FRAMEWORK_FORMAT_YUV_420_888:
m_yuv_converter.reset(
diff --git a/stream-servers/FrameworkFormats.h b/stream-servers/FrameworkFormats.h
index 051f3331..d6ca5f79 100644
--- a/stream-servers/FrameworkFormats.h
+++ b/stream-servers/FrameworkFormats.h
@@ -17,4 +17,5 @@ enum FrameworkFormat {
FRAMEWORK_FORMAT_YV12 = 1,
FRAMEWORK_FORMAT_YUV_420_888 = 2,
FRAMEWORK_FORMAT_NV12 = 3,
+ FRAMEWORK_FORMAT_P010 = 4,
};
diff --git a/stream-servers/YUVConverter.cpp b/stream-servers/YUVConverter.cpp
index 55ce31d2..10e97c50 100644
--- a/stream-servers/YUVConverter.cpp
+++ b/stream-servers/YUVConverter.cpp
@@ -22,6 +22,7 @@
#include "DispatchTables.h"
#include "host-common/feature_control.h"
+#include "host-common/misc.h"
#define FATAL(fmt,...) do { \
@@ -42,6 +43,7 @@
bool isInterleaved(FrameworkFormat format) {
switch (format) {
case FRAMEWORK_FORMAT_NV12:
+ case FRAMEWORK_FORMAT_P010:
return true;
case FRAMEWORK_FORMAT_YUV_420_888:
return feature_is_enabled(kFeature_YUV420888toNV21);
@@ -65,6 +67,7 @@ YUVInterleaveDirection getInterleaveDirection(FrameworkFormat format) {
switch (format) {
case FRAMEWORK_FORMAT_NV12:
+ case FRAMEWORK_FORMAT_P010:
return YUVInterleaveDirection::UV;
case FRAMEWORK_FORMAT_YUV_420_888:
if (feature_is_enabled(kFeature_YUV420888toNV21)) {
@@ -125,6 +128,17 @@ GLint getGlTextureFormat(FrameworkFormat format, YUVPlane plane) {
FATAL("Invalid plane:%d for format:%d", plane, format);
return 0;
}
+ case FRAMEWORK_FORMAT_P010:
+ switch (plane) {
+ case YUVPlane::Y:
+ return GL_R16UI;
+ case YUVPlane::UV:
+ return GL_RG16UI;
+ case YUVPlane::U:
+ case YUVPlane::V:
+ FATAL("Invalid plane:%d for format:%d", plane, format);
+ return 0;
+ }
default:
FATAL("Invalid format:%d", format);
return 0;
@@ -177,6 +191,17 @@ GLenum getGlPixelFormat(FrameworkFormat format, YUVPlane plane) {
FATAL("Invalid plane:%d for format:%d", plane, format);
return 0;
}
+ case FRAMEWORK_FORMAT_P010:
+ switch (plane) {
+ case YUVPlane::Y:
+ return GL_RED_INTEGER;
+ case YUVPlane::UV:
+ return GL_RG_INTEGER;
+ case YUVPlane::U:
+ case YUVPlane::V:
+ FATAL("Invalid plane:%d for format:%d", plane, format);
+ return 0;
+ }
default:
FATAL("Invalid format:%d", format);
return 0;
@@ -227,6 +252,16 @@ GLsizei getGlPixelType(FrameworkFormat format, YUVPlane plane) {
FATAL("Invalid plane:%d for format:%d", plane, format);
return 0;
}
+ case FRAMEWORK_FORMAT_P010:
+ switch (plane) {
+ case YUVPlane::Y:
+ case YUVPlane::UV:
+ return GL_UNSIGNED_SHORT;
+ case YUVPlane::U:
+ case YUVPlane::V:
+ FATAL("Invalid plane:%d for format:%d", plane, format);
+ return 0;
+ }
default:
FATAL("Invalid format:%d", format);
return 0;
@@ -325,6 +360,17 @@ static void getYUVOffsets(int width,
*yWidth = yStride;
*cWidth = cStride / 2;
break;
+ case FRAMEWORK_FORMAT_P010:
+ *yWidth = width;
+ *cWidth = width / 2;
+ yStride = width * /*bytes per pixel=*/2;
+ cStride = *cWidth * /*bytes per pixel=*/2;
+ cHeight = height / 2;
+ cSize = cStride * cHeight;
+ *yOffset = 0;
+ *uOffset = yStride * height;
+ *vOffset = (*uOffset) + 2;
+ break;
case FRAMEWORK_FORMAT_GL_COMPATIBLE:
FATAL("Input not a YUV format! (FRAMEWORK_FORMAT_GL_COMPATIBLE)");
default:
@@ -408,19 +454,13 @@ static void subUpdateYUVGLTex(GLenum texture_unit,
s_gles2.glActiveTexture(GL_TEXTURE0);
}
-// createYUVGLShader() defines the vertex/fragment
-// shader that does the actual work of converting
-// YUV to RGB. The resulting program is stored in |outProgram|.
-static void createYUVGLShader(FrameworkFormat format,
- GLuint* outProgram,
- GLint* outUniformLocYWidthCutoff,
- GLint* outUniformLocCWidthCutoff,
- GLint* outUniformLocSamplerY,
- GLint* outUniformLocSamplerU,
- GLint* outUniformLocSamplerV,
- GLint* outAttributeLocTexCoord,
- GLint* outAttributeLocPos) {
- YUV_DEBUG_LOG("format:%d", format);
+void YUVConverter::createYUVGLShader() {
+ YUV_DEBUG_LOG("format:%d", mFormat);
+
+ // P010 needs uint samplers.
+ if (mFormat == FRAMEWORK_FORMAT_P010 && !mHasGlsl3Support) {
+ return;
+ }
static const char kVertShader[] = R"(
precision highp float;
@@ -433,6 +473,8 @@ void main(void) {
}
)";
+ static const char kFragShaderVersion3[] = R"(#version 300 es)";
+
static const char kFragShaderBegin[] = R"(
precision highp float;
@@ -440,10 +482,20 @@ varying highp vec2 vTexCoord;
uniform highp float uYWidthCutoff;
uniform highp float uCWidthCutoff;
+ )";
+
+ static const char kSamplerUniforms[] = R"(
uniform sampler2D uSamplerY;
uniform sampler2D uSamplerU;
uniform sampler2D uSamplerV;
+ )";
+ static const char kSamplerUniformsUint[] = R"(
+uniform usampler2D uSamplerY;
+uniform usampler2D uSamplerU;
+uniform usampler2D uSamplerV;
+ )";
+ static const char kFragShaderMainBegin[] = R"(
void main(void) {
highp vec2 yTexCoords = vTexCoord;
highp vec2 uvTexCoords = vTexCoord;
@@ -454,9 +506,11 @@ void main(void) {
uvTexCoords.y *= uCWidthCutoff;
highp vec3 yuv;
- yuv[0] = texture2D(uSamplerY, yTexCoords).r;
)";
+ static const char kSampleY[] = R"(
+ yuv[0] = texture2D(uSamplerY, yTexCoords).r;
+ )";
static const char kSampleUV[] = R"(
yuv[1] = texture2D(uSamplerU, uvTexCoords).r;
yuv[2] = texture2D(uSamplerV, uvTexCoords).r;
@@ -472,7 +526,18 @@ void main(void) {
yuv[2] = texture2D(uSamplerV, uvTexCoords).r;
)";
- static const char kFragShaderEnd[] = R"(
+ static const char kSampleP010[] = R"(
+ uint yRaw = texture(uSamplerY, yTexCoords).r;
+ uint uRaw = texture(uSamplerU, uvTexCoords).r;
+ uint vRaw = texture(uSamplerV, uvTexCoords).g;
+
+ // P010 values are stored in the upper 10-bits of 16-bit unsigned shorts.
+ yuv[0] = float(yRaw >> 6) / 1023.0;
+ yuv[1] = float(uRaw >> 6) / 1023.0;
+ yuv[2] = float(vRaw >> 6) / 1023.0;
+ )";
+
+ static const char kFragShaderMainEnd[] = R"(
yuv[0] = yuv[0] - 0.0625;
yuv[1] = 0.96 * (yuv[1] - 0.5);
yuv[2] = (yuv[2] - 0.5);
@@ -487,26 +552,53 @@ void main(void) {
)";
std::string vertShaderSource(kVertShader);
- std::string fragShaderSource(kFragShaderBegin);
+ std::string fragShaderSource;
- if (isInterleaved(format)) {
- if (getInterleaveDirection(format) == YUVInterleaveDirection::UV) {
- fragShaderSource += kSampleInterleavedUV;
+ if (mFormat == FRAMEWORK_FORMAT_P010) {
+ fragShaderSource += kFragShaderVersion3;
+ }
+
+ fragShaderSource += kFragShaderBegin;
+
+ if (mFormat == FRAMEWORK_FORMAT_P010) {
+ fragShaderSource += kSamplerUniformsUint;
+ } else {
+ fragShaderSource += kSamplerUniforms;
+ }
+
+ fragShaderSource += kFragShaderMainBegin;
+
+ switch (mFormat) {
+ case FRAMEWORK_FORMAT_NV12:
+ case FRAMEWORK_FORMAT_YUV_420_888:
+ case FRAMEWORK_FORMAT_YV12:
+ fragShaderSource += kSampleY;
+ if (isInterleaved(mFormat)) {
+ if (getInterleaveDirection(mFormat) == YUVInterleaveDirection::UV) {
+ fragShaderSource += kSampleInterleavedUV;
+ } else {
+ fragShaderSource += kSampleInterleavedVU;
+ }
} else {
- fragShaderSource += kSampleInterleavedVU;
+ fragShaderSource += kSampleUV;
}
- } else {
- fragShaderSource += kSampleUV;
+ break;
+ case FRAMEWORK_FORMAT_P010:
+ fragShaderSource += kSampleP010;
+ break;
+ default:
+ FATAL("%s: invalid format:%d", __FUNCTION__, mFormat);
+ return;
}
- fragShaderSource += kFragShaderEnd;
+ fragShaderSource += kFragShaderMainEnd;
- YUV_DEBUG_LOG("format:%d vert-source:%s frag-source:%s", format, vertShaderSource.c_str(), fragShaderSource.c_str());
+ YUV_DEBUG_LOG("format:%d vert-source:%s frag-source:%s", mFormat, vertShaderSource.c_str(), fragShaderSource.c_str());
- const GLchar* const vertShaderSourceChars = static_cast<const GLchar*>(kVertShader);
+ const GLchar* const vertShaderSourceChars = vertShaderSource.c_str();
const GLchar* const fragShaderSourceChars = fragShaderSource.c_str();
- const GLint vertShaderSourceLen = strlen(kVertShader);
- const GLint fragShaderSourceLen = strlen(fragShaderSourceChars);
+ const GLint vertShaderSourceLen = vertShaderSource.length();
+ const GLint fragShaderSourceLen = fragShaderSource.length();
GLuint vertShader = s_gles2.glCreateShader(GL_VERTEX_SHADER);
GLuint fragShader = s_gles2.glCreateShader(GL_FRAGMENT_SHADER);
@@ -527,56 +619,37 @@ void main(void) {
}
}
- *outProgram = s_gles2.glCreateProgram();
- s_gles2.glAttachShader(*outProgram, vertShader);
- s_gles2.glAttachShader(*outProgram, fragShader);
- s_gles2.glLinkProgram(*outProgram);
+ mProgram = s_gles2.glCreateProgram();
+ s_gles2.glAttachShader(mProgram, vertShader);
+ s_gles2.glAttachShader(mProgram, fragShader);
+ s_gles2.glLinkProgram(mProgram);
GLint status = GL_FALSE;
- s_gles2.glGetProgramiv(*outProgram, GL_LINK_STATUS, &status);
+ s_gles2.glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLchar error[1024];
- s_gles2.glGetProgramInfoLog(*outProgram, sizeof(error), 0, &error[0]);
+ s_gles2.glGetProgramInfoLog(mProgram, sizeof(error), 0, &error[0]);
FATAL("Failed to link YUV conversion program: %s", error);
- s_gles2.glDeleteProgram(*outProgram);
- *outProgram = 0;
+ s_gles2.glDeleteProgram(mProgram);
+ mProgram = 0;
return;
}
- *outUniformLocYWidthCutoff = s_gles2.glGetUniformLocation(*outProgram, "uYWidthCutoff");
- *outUniformLocCWidthCutoff = s_gles2.glGetUniformLocation(*outProgram, "uCWidthCutoff");
- *outUniformLocSamplerY = s_gles2.glGetUniformLocation(*outProgram, "uSamplerY");
- *outUniformLocSamplerU = s_gles2.glGetUniformLocation(*outProgram, "uSamplerU");
- *outUniformLocSamplerV = s_gles2.glGetUniformLocation(*outProgram, "uSamplerV");
- *outAttributeLocPos = s_gles2.glGetAttribLocation(*outProgram, "aPosition");
- *outAttributeLocTexCoord = s_gles2.glGetAttribLocation(*outProgram, "aTexCoord");
-
- YUV_DEBUG_LOG("locations: %d %d %d %d %d %d %d",
- *outUniformLocYWidthCutoff, *outUniformLocCWidthCutoff,
- *outUniformLocSamplerY, *outUniformLocSamplerU, *outUniformLocSamplerV,
- *outAttributeLocPos, *outAttributeLocTexCoord);
+ mUniformLocYWidthCutoff = s_gles2.glGetUniformLocation(mProgram, "uYWidthCutoff");
+ mUniformLocCWidthCutoff = s_gles2.glGetUniformLocation(mProgram, "uCWidthCutoff");
+ mUniformLocSamplerY = s_gles2.glGetUniformLocation(mProgram, "uSamplerY");
+ mUniformLocSamplerU = s_gles2.glGetUniformLocation(mProgram, "uSamplerU");
+ mUniformLocSamplerV = s_gles2.glGetUniformLocation(mProgram, "uSamplerV");
+ mAttributeLocPos = s_gles2.glGetAttribLocation(mProgram, "aPosition");
+ mAttributeLocTexCoord = s_gles2.glGetAttribLocation(mProgram, "aTexCoord");
s_gles2.glDeleteShader(vertShader);
s_gles2.glDeleteShader(fragShader);
}
-
-// When converting YUV to RGB with shaders,
-// we are using the OpenGL graphics pipeline to do compute,
-// so we need to express the place to store the result
-// with triangles and draw calls.
-// createYUVGLFullscreenQuad() defines a fullscreen quad
-// with position and texture coordinates.
-// The quad will be textured with the resulting RGB colors,
-// and we will read back the pixels from the framebuffer
-// to retrieve our RGB result.
-static void createYUVGLFullscreenQuad(GLuint* outVertexBuffer,
- GLuint* outIndexBuffer) {
- assert(outVertexBuffer);
- assert(outIndexBuffer);
-
- s_gles2.glGenBuffers(1, outVertexBuffer);
- s_gles2.glGenBuffers(1, outIndexBuffer);
+void YUVConverter::createYUVGLFullscreenQuad() {
+ s_gles2.glGenBuffers(1, &mQuadVertexBuffer);
+ s_gles2.glGenBuffers(1, &mQuadIndexBuffer);
static const float kVertices[] = {
+1, -1, +0, +1, +0,
@@ -587,9 +660,9 @@ static void createYUVGLFullscreenQuad(GLuint* outVertexBuffer,
static const GLubyte kIndices[] = { 0, 1, 2, 2, 3, 0 };
- s_gles2.glBindBuffer(GL_ARRAY_BUFFER, *outVertexBuffer);
+ s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
s_gles2.glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW);
- s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *outIndexBuffer);
+ s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadIndexBuffer);
s_gles2.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndices), kIndices, GL_STATIC_DRAW);
}
@@ -670,17 +743,14 @@ void YUVConverter::init(int width, int height, FrameworkFormat format) {
}
}
- createYUVGLShader(mFormat,
- &mProgram,
- &mUniformLocYWidthCutoff,
- &mUniformLocCWidthCutoff,
- &mUniformLocSamplerY,
- &mUniformLocSamplerU,
- &mUniformLocSamplerV,
- &mAttributeLocTexCoord,
- &mAttributeLocPos);
-
- createYUVGLFullscreenQuad(&mQuadVertexBuffer, &mQuadIndexBuffer);
+ int glesMajor;
+ int glesMinor;
+ emugl::getGlesVersion(&glesMajor, &glesMinor);
+ mHasGlsl3Support = glesMajor >= 3;
+ YUV_DEBUG_LOG("YUVConverter has GLSL ES 3 support:%s (major:%d minor:%d", (mHasGlsl3Support ? "yes" : "no"), glesMajor, glesMinor);
+
+ createYUVGLShader();
+ createYUVGLFullscreenQuad();
}
void YUVConverter::saveGLState() {
@@ -758,6 +828,12 @@ void YUVConverter::drawConvert(int x, int y, int width, int height, const char*
if (mProgram == 0) {
init(width, height, mFormat);
}
+
+ if (mFormat == FRAMEWORK_FORMAT_P010 && !mHasGlsl3Support) {
+ // TODO: perhaps fallback to just software conversion.
+ return;
+ }
+
s_gles2.glViewport(x, y, width, height);
uint32_t yOffset, uOffset, vOffset, ywidth, cwidth, cheight;
getYUVOffsets(width, height, mFormat, &yOffset, &uOffset, &vOffset, &ywidth, &cwidth);
@@ -809,11 +885,9 @@ void YUVConverter::updateCutoffs(float width, float ywidth,
mYWidthCutoff = ((float)width) / ((float)ywidth);
mCWidthCutoff = ((float)halfwidth) / ((float)cwidth);
break;
- case FRAMEWORK_FORMAT_YUV_420_888:
- mYWidthCutoff = 1.0f;
- mCWidthCutoff = 1.0f;
- break;
case FRAMEWORK_FORMAT_NV12:
+ case FRAMEWORK_FORMAT_P010:
+ case FRAMEWORK_FORMAT_YUV_420_888:
mYWidthCutoff = 1.0f;
mCWidthCutoff = 1.0f;
break;
diff --git a/stream-servers/YUVConverter.h b/stream-servers/YUVConverter.h
index 8f2ea073..0140f896 100644
--- a/stream-servers/YUVConverter.h
+++ b/stream-servers/YUVConverter.h
@@ -82,8 +82,12 @@ private:
void init(int w, int h, FrameworkFormat format);
void reset();
+ void createYUVGLShader();
+ void createYUVGLFullscreenQuad();
+
// For dealing with n-pixel-aligned buffers
void updateCutoffs(float width, float ywidth, float halfwidth, float cwidth);
+
int mWidth = 0;
int mHeight = 0;
FrameworkFormat mFormat;
@@ -96,16 +100,17 @@ private:
GLuint mTextureY = 0;
GLuint mTextureU = 0;
GLuint mTextureV = 0;
- // shader uniform locations
GLint mUniformLocYWidthCutoff = -1;
GLint mUniformLocCWidthCutoff = -1;
GLint mUniformLocSamplerY = -1;
GLint mUniformLocSamplerU = -1;
GLint mUniformLocSamplerV = -1;
- GLint mAttributeLocTexCoord = -1;
GLint mAttributeLocPos = -1;
+ GLint mAttributeLocTexCoord = -1;
+
float mYWidthCutoff = 1.0;
float mCWidthCutoff = 1.0;
+ bool mHasGlsl3Support = false;
// YUVConverter can end up being used
// in a TextureDraw / subwindow context, and subsequently
diff --git a/stream-servers/virtio-gpu-gfxstream-renderer.cpp b/stream-servers/virtio-gpu-gfxstream-renderer.cpp
index 0cb0af6f..f469fc39 100644
--- a/stream-servers/virtio-gpu-gfxstream-renderer.cpp
+++ b/stream-servers/virtio-gpu-gfxstream-renderer.cpp
@@ -202,6 +202,7 @@ static inline uint32_t align_up_power_of_2(uint32_t n, uint32_t a) {
#define VIRGL_FORMAT_NV12 166
#define VIRGL_FORMAT_YV12 163
+#define VIRGL_FORMAT_P010 314
const uint32_t kGlBgra = 0x80e1;
const uint32_t kGlRgba = 0x1908;
@@ -220,6 +221,7 @@ constexpr uint32_t kFwkFormatGlCompat = 0;
constexpr uint32_t kFwkFormatYV12 = 1;
// constexpr uint32_t kFwkFormatYUV420888 = 2;
constexpr uint32_t kFwkFormatNV12 = 3;
+constexpr uint32_t kFwkFormatP010 = 4;
static inline bool virgl_format_is_yuv(uint32_t format) {
switch (format) {
@@ -235,6 +237,7 @@ static inline bool virgl_format_is_yuv(uint32_t format) {
case VIRGL_FORMAT_R10G10B10A2_UNORM:
return false;
case VIRGL_FORMAT_NV12:
+ case VIRGL_FORMAT_P010:
case VIRGL_FORMAT_YV12:
return true;
default:
@@ -262,6 +265,7 @@ static inline uint32_t virgl_format_to_gl(uint32_t virgl_format) {
case VIRGL_FORMAT_R8G8_UNORM:
return kGlRg8;
case VIRGL_FORMAT_NV12:
+ case VIRGL_FORMAT_P010:
case VIRGL_FORMAT_YV12:
// emulated as RGBA8888
return kGlRgba;
@@ -276,6 +280,8 @@ static inline uint32_t virgl_format_to_fwk_format(uint32_t virgl_format) {
switch (virgl_format) {
case VIRGL_FORMAT_NV12:
return kFwkFormatNV12;
+ case VIRGL_FORMAT_P010:
+ return kFwkFormatP010;
case VIRGL_FORMAT_YV12:
return kFwkFormatYV12;
case VIRGL_FORMAT_R8_UNORM:
@@ -349,10 +355,11 @@ static inline size_t virgl_format_to_total_xfer_len(
uint32_t totalWidth, uint32_t totalHeight,
uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
if (virgl_format_is_yuv(format)) {
+ uint32_t bpp = format == VIRGL_FORMAT_P010 ? 2 : 1;
uint32_t yAlign = (format == VIRGL_FORMAT_YV12) ? 32 : 16;
uint32_t yWidth = totalWidth;
uint32_t yHeight = totalHeight;
- uint32_t yStride = align_up_power_of_2(yWidth, yAlign);
+ uint32_t yStride = align_up_power_of_2(yWidth, yAlign) * bpp;
uint32_t ySize = yStride * yHeight;
uint32_t uvAlign = 16;
@@ -361,6 +368,9 @@ static inline size_t virgl_format_to_total_xfer_len(
if (format == VIRGL_FORMAT_NV12) {
uvWidth = totalWidth;
uvPlaneCount = 1;
+ } else if (format == VIRGL_FORMAT_P010) {
+ uvWidth = totalWidth;
+ uvPlaneCount = 1;
} else if (format == VIRGL_FORMAT_YV12) {
uvWidth = totalWidth / 2;
uvPlaneCount = 2;
@@ -368,7 +378,7 @@ static inline size_t virgl_format_to_total_xfer_len(
VGP_FATAL() << "Unknown yuv virgl format: 0x" << std::hex << format;
}
uint32_t uvHeight = totalHeight / 2;
- uint32_t uvStride = align_up_power_of_2(uvWidth, uvAlign);
+ uint32_t uvStride = align_up_power_of_2(uvWidth, uvAlign) * bpp;
uint32_t uvSize = uvStride * uvHeight * uvPlaneCount;
uint32_t dataSize = ySize + uvSize;