metal: Implement SDL_LockTexture for non-YUV textures.
authorAlex Szpakowski <slime73@gmail.com>
Tue, 18 Dec 2018 14:23:05 -0400
changeset 12480bc0bc8a54387
parent 12479 f2c510ee0f2a
child 12481 10fc11bbc967
metal: Implement SDL_LockTexture for non-YUV textures.
src/render/metal/SDL_render_metal.m
     1.1 --- a/src/render/metal/SDL_render_metal.m	Sun Dec 16 11:15:21 2018 +0100
     1.2 +++ b/src/render/metal/SDL_render_metal.m	Tue Dec 18 14:23:05 2018 -0400
     1.3 @@ -155,6 +155,9 @@
     1.4      @property (nonatomic, assign) BOOL nv12;
     1.5      @property (nonatomic, assign) size_t conversionBufferOffset;
     1.6      @property (nonatomic, assign) BOOL hasdata;
     1.7 +
     1.8 +    @property (nonatomic, retain) id<MTLBuffer> lockedbuffer;
     1.9 +    @property (nonatomic, assign) SDL_Rect lockedrect;
    1.10  @end
    1.11  
    1.12  @implementation METAL_TextureData
    1.13 @@ -783,15 +786,72 @@
    1.14  static int
    1.15  METAL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    1.16                 const SDL_Rect * rect, void **pixels, int *pitch)
    1.17 -{
    1.18 -    return SDL_Unsupported();   // !!! FIXME: write me
    1.19 -}
    1.20 +{ @autoreleasepool {
    1.21 +    METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
    1.22 +    METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
    1.23 +
    1.24 +    if (texturedata.yuv || texturedata.nv12) {
    1.25 +        /* FIXME: write me */
    1.26 +        return SDL_Unsupported();
    1.27 +    }
    1.28 +
    1.29 +    *pitch = SDL_BYTESPERPIXEL(texture->format) * rect->w;
    1.30 +
    1.31 +    texturedata.lockedrect = *rect;
    1.32 +    texturedata.lockedbuffer = [data.mtldevice newBufferWithLength:(*pitch)*rect->h options:MTLResourceStorageModeShared];
    1.33 +    if (texturedata.lockedbuffer == nil) {
    1.34 +        return SDL_OutOfMemory();
    1.35 +    }
    1.36 +
    1.37 +    *pixels = [texturedata.lockedbuffer contents];
    1.38 +
    1.39 +    return 0;
    1.40 +}}
    1.41  
    1.42  static void
    1.43  METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
    1.44 -{
    1.45 -    // !!! FIXME: write me
    1.46 -}
    1.47 +{ @autoreleasepool {
    1.48 +    METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
    1.49 +    METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
    1.50 +    SDL_Rect rect = texturedata.lockedrect;
    1.51 +
    1.52 +    if (texturedata.lockedbuffer == nil) {
    1.53 +        return;
    1.54 +    }
    1.55 +
    1.56 +    if (data.mtlcmdencoder != nil) {
    1.57 +        [data.mtlcmdencoder endEncoding];
    1.58 +        data.mtlcmdencoder = nil;
    1.59 +    }
    1.60 +
    1.61 +    if (data.mtlcmdbuffer == nil) {
    1.62 +        data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
    1.63 +    }
    1.64 +
    1.65 +    id<MTLBlitCommandEncoder> blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
    1.66 +
    1.67 +    [blitcmd copyFromBuffer:texturedata.lockedbuffer
    1.68 +               sourceOffset:0
    1.69 +          sourceBytesPerRow:SDL_BYTESPERPIXEL(texture->format) * rect.w
    1.70 +        sourceBytesPerImage:0
    1.71 +                 sourceSize:MTLSizeMake(rect.w, rect.h, 1)
    1.72 +                  toTexture:texturedata.mtltexture
    1.73 +           destinationSlice:0
    1.74 +           destinationLevel:0
    1.75 +          destinationOrigin:MTLOriginMake(rect.x, rect.y, 0)];
    1.76 +
    1.77 +    [blitcmd endEncoding];
    1.78 +
    1.79 +    [data.mtlcmdbuffer commit];
    1.80 +    data.mtlcmdbuffer = nil;
    1.81 +
    1.82 +#if !__has_feature(objc_arc)
    1.83 +    [texturedata.lockedbuffer release];
    1.84 +#endif
    1.85 +
    1.86 +    texturedata.lockedbuffer = nil;
    1.87 +    texturedata.hasdata = YES;
    1.88 +}}
    1.89  
    1.90  static int
    1.91  METAL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)