@@ -1336,22 +1336,34 @@ static VALUE Renderer_present(VALUE self)
13361336}
13371337
13381338/*
1339- * Read pixels from the current rendering target.
1339+ * @overload read_pixels(rect, format)
1340+ * Read pixels from the current rendering target.
13401341 *
1341- * @param rect [SDL2::Rect,nil] the area to read (the entire target if nil)
1342- * @param format [Integer] the desired pixel format (0 for ARGB8888)
1343- * @return [String] raw pixel data as a binary string (ARGB8888 by default)
1342+ * This is a very slow operation and should not be used frequently.
1343+ * Call this after rendering but before {#present}.
13441344 *
1345- * @example
1346- * # Read the entire screen before presenting
1347- * pixels = renderer.read_pixels(nil, 0)
1345+ * @param rect [SDL2::Rect, nil] the area to read (nil for the entire target)
1346+ * @param format [SDL2::PixelFormat, Integer] the desired pixel format
1347+ * (0 to use the format of the rendering target)
1348+ * @return [String] raw pixel data as a binary string
1349+ *
1350+ * @example Read the entire screen in the rendering target's native format
1351+ * pixels = renderer.read_pixels(nil, 0)
1352+ *
1353+ * @example Read a sub-region in ARGB8888
1354+ * rect = SDL2::Rect.new(10, 10, 100, 100)
1355+ * pixels = renderer.read_pixels(rect, SDL2::PixelFormat::ARGB8888)
1356+ *
1357+ * @raise [SDL2::Error] raised on failure
1358+ * @see https://wiki.libsdl.org/SDL2/SDL_RenderReadPixels SDL_RenderReadPixels
13481359 */
13491360static VALUE Renderer_read_pixels (VALUE self , VALUE rect , VALUE format )
13501361{
13511362 SDL_Renderer * renderer = Get_SDL_Renderer (self );
13521363 SDL_Rect sdl_rect ;
13531364 SDL_Rect * rect_ptr = NULL ;
1354- Uint32 fmt = NUM2UINT (format );
1365+ Uint32 fmt = uint32_for_format (format );
1366+ Uint32 pitch_fmt ;
13551367 int w , h , pitch ;
13561368 void * pixels ;
13571369 VALUE result ;
@@ -1365,10 +1377,18 @@ static VALUE Renderer_read_pixels(VALUE self, VALUE rect, VALUE format)
13651377 HANDLE_ERROR (SDL_GetRendererOutputSize (renderer , & w , & h ));
13661378 }
13671379
1368- if (fmt == 0 )
1369- fmt = SDL_PIXELFORMAT_ARGB8888 ;
1380+ /* When fmt is 0 SDL uses the rendering target's format, so we need
1381+ to query it to calculate the correct pitch and buffer size. */
1382+ if (fmt == 0 ) {
1383+ SDL_RendererInfo info ;
1384+ HANDLE_ERROR (SDL_GetRendererInfo (renderer , & info ));
1385+ pitch_fmt = (info .num_texture_formats > 0 )
1386+ ? info .texture_formats [0 ] : SDL_PIXELFORMAT_ARGB8888 ;
1387+ } else {
1388+ pitch_fmt = fmt ;
1389+ }
13701390
1371- pitch = w * SDL_BYTESPERPIXEL (fmt );
1391+ pitch = w * SDL_BYTESPERPIXEL (pitch_fmt );
13721392 pixels = ruby_xmalloc (pitch * h );
13731393
13741394 if (SDL_RenderReadPixels (renderer , rect_ptr , fmt , pixels , pitch ) < 0 ) {
0 commit comments