Skip to content
Permalink
Browse files

metal: Implement SDL_LockTexture for YUV formats.

  • Loading branch information
slime73 committed Dec 19, 2018
1 parent ce8c716 commit c7db6ade7dc126a39ecd658c3d1984c7f78ddac7
Showing with 53 additions and 5 deletions.
  1. +53 −5 src/render/metal/SDL_render_metal.m
@@ -789,16 +789,22 @@ - (void)dealloc
{ @autoreleasepool {
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
int buffersize = 0;

if (texturedata.yuv || texturedata.nv12) {
/* FIXME: write me */
return SDL_Unsupported();
if (rect->w <= 0 || rect->h <= 0) {
return SDL_SetError("Invalid rectangle dimensions for LockTexture.");
}

*pitch = SDL_BYTESPERPIXEL(texture->format) * rect->w;

if (texturedata.yuv || texturedata.nv12) {
buffersize = ((*pitch) * rect->h) + (2 * (*pitch + 1) / 2) * ((rect->h + 1) / 2);
} else {
buffersize = (*pitch) * rect->h;
}

texturedata.lockedrect = *rect;
texturedata.lockedbuffer = [data.mtldevice newBufferWithLength:(*pitch)*rect->h options:MTLResourceStorageModeShared];
texturedata.lockedbuffer = [data.mtldevice newBufferWithLength:buffersize options:MTLResourceStorageModeShared];
if (texturedata.lockedbuffer == nil) {
return SDL_OutOfMemory();
}
@@ -814,6 +820,8 @@ - (void)dealloc
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
SDL_Rect rect = texturedata.lockedrect;
int pitch = SDL_BYTESPERPIXEL(texture->format) * rect.w;
SDL_Rect UVrect = {rect.x / 2, rect.y / 2, (rect.w + 1) / 2, (rect.h + 1) / 2};

if (texturedata.lockedbuffer == nil) {
return;
@@ -832,14 +840,54 @@ - (void)dealloc

[blitcmd copyFromBuffer:texturedata.lockedbuffer
sourceOffset:0
sourceBytesPerRow:SDL_BYTESPERPIXEL(texture->format) * rect.w
sourceBytesPerRow:pitch
sourceBytesPerImage:0
sourceSize:MTLSizeMake(rect.w, rect.h, 1)
toTexture:texturedata.mtltexture
destinationSlice:0
destinationLevel:0
destinationOrigin:MTLOriginMake(rect.x, rect.y, 0)];

if (texturedata.yuv) {
int Uslice = texture->format == SDL_PIXELFORMAT_YV12 ? 1 : 0;
int Vslice = texture->format == SDL_PIXELFORMAT_YV12 ? 0 : 1;
int UVpitch = (pitch + 1) / 2;

[blitcmd copyFromBuffer:texturedata.lockedbuffer
sourceOffset:rect.h * pitch
sourceBytesPerRow:UVpitch
sourceBytesPerImage:UVpitch * UVrect.h
sourceSize:MTLSizeMake(UVrect.w, UVrect.h, 1)
toTexture:texturedata.mtltexture_uv
destinationSlice:Uslice
destinationLevel:0
destinationOrigin:MTLOriginMake(UVrect.x, UVrect.y, 0)];

[blitcmd copyFromBuffer:texturedata.lockedbuffer
sourceOffset:(rect.h * pitch) + UVrect.h * UVpitch
sourceBytesPerRow:UVpitch
sourceBytesPerImage:UVpitch * UVrect.h
sourceSize:MTLSizeMake(UVrect.w, UVrect.h, 1)
toTexture:texturedata.mtltexture_uv
destinationSlice:Vslice
destinationLevel:0
destinationOrigin:MTLOriginMake(UVrect.x, UVrect.y, 0)];
}

if (texturedata.nv12) {
int UVpitch = 2 * ((pitch + 1) / 2);

[blitcmd copyFromBuffer:texturedata.lockedbuffer
sourceOffset:rect.h * pitch
sourceBytesPerRow:UVpitch
sourceBytesPerImage:0
sourceSize:MTLSizeMake(UVrect.w, UVrect.h, 1)
toTexture:texturedata.mtltexture_uv
destinationSlice:0
destinationLevel:0
destinationOrigin:MTLOriginMake(UVrect.x, UVrect.y, 0)];
}

[blitcmd endEncoding];

[data.mtlcmdbuffer commit];

0 comments on commit c7db6ad

Please sign in to comment.