src/render/metal/SDL_render_metal.m
changeset 12322 b5074e5aaa49
parent 12320 758d4e1222a7
child 12381 dc9108cd4340
equal deleted inserted replaced
12321:4216eccf4ea2 12322:b5074e5aaa49
  1349 
  1349 
  1350 static int
  1350 static int
  1351 METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1351 METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1352                     Uint32 pixel_format, void * pixels, int pitch)
  1352                     Uint32 pixel_format, void * pixels, int pitch)
  1353 { @autoreleasepool {
  1353 { @autoreleasepool {
       
  1354     METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
       
  1355 
       
  1356     /* Make sure we have a valid MTLTexture to read from, and an active command
       
  1357      * buffer we can wait for. */
  1354     METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad);
  1358     METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad);
  1355 
  1359 
  1356     // !!! FIXME: this probably needs to commit the current command buffer, and probably waitUntilCompleted
  1360     /* Wait for the current command buffer to finish, so we don't read from the
  1357     METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
  1361      * texture before the GPU finishes rendering to it. */
       
  1362     if (data.mtlcmdencoder) {
       
  1363         [data.mtlcmdencoder endEncoding];
       
  1364         [data.mtlcmdbuffer commit];
       
  1365         [data.mtlcmdbuffer waitUntilCompleted];
       
  1366 
       
  1367         data.mtlcmdencoder = nil;
       
  1368         data.mtlcmdbuffer = nil;
       
  1369     }
       
  1370 
  1358     id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
  1371     id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
  1359     MTLRegion mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
  1372     MTLRegion mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
  1360 
  1373 
  1361     // we only do BGRA8 or RGBA8 at the moment, so 4 will do.
  1374     // we only do BGRA8 or RGBA8 at the moment, so 4 will do.
  1362     const int temp_pitch = rect->w * 4;
  1375     const int temp_pitch = rect->w * 4;
  1368     [mtltexture getBytes:temp_pixels bytesPerRow:temp_pitch fromRegion:mtlregion mipmapLevel:0];
  1381     [mtltexture getBytes:temp_pixels bytesPerRow:temp_pitch fromRegion:mtlregion mipmapLevel:0];
  1369 
  1382 
  1370     const Uint32 temp_format = (mtltexture.pixelFormat == MTLPixelFormatBGRA8Unorm) ? SDL_PIXELFORMAT_ARGB8888 : SDL_PIXELFORMAT_ABGR8888;
  1383     const Uint32 temp_format = (mtltexture.pixelFormat == MTLPixelFormatBGRA8Unorm) ? SDL_PIXELFORMAT_ARGB8888 : SDL_PIXELFORMAT_ABGR8888;
  1371     const int status = SDL_ConvertPixels(rect->w, rect->h, temp_format, temp_pixels, temp_pitch, pixel_format, pixels, pitch);
  1384     const int status = SDL_ConvertPixels(rect->w, rect->h, temp_format, temp_pixels, temp_pitch, pixel_format, pixels, pitch);
  1372     SDL_free(temp_pixels);
  1385     SDL_free(temp_pixels);
       
  1386 
       
  1387     /* Set up an active command buffer and encoder once we're done. It will use
       
  1388      * the same texture that was active before (even if it's part of the swap
       
  1389      * chain), since we didn't clear that when waiting for the command buffer to
       
  1390      * complete. */
       
  1391     METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad);
       
  1392 
  1373     return status;
  1393     return status;
  1374 }}
  1394 }}
  1375 
  1395 
  1376 static void
  1396 static void
  1377 METAL_RenderPresent(SDL_Renderer * renderer)
  1397 METAL_RenderPresent(SDL_Renderer * renderer)