You can specify the format for pixel data in SDL_RenderReadPixels() and SDL_RenderWritePixels()
authorSam Lantinga <slouken@libsdl.org>
Mon, 16 Nov 2009 07:13:07 +0000
changeset 34359f62f47d989b
parent 3434 147d6ef5be03
child 3436 0538362b98d3
You can specify the format for pixel data in SDL_RenderReadPixels() and SDL_RenderWritePixels()
This code still doesn't quite work yet. :)
include/SDL_video.h
src/video/SDL_renderer_gl.c
src/video/SDL_renderer_sw.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
test/automated/common/common.h
test/automated/render/render.c
     1.1 --- a/include/SDL_video.h	Sun Nov 15 09:21:46 2009 +0000
     1.2 +++ b/include/SDL_video.h	Mon Nov 16 07:13:07 2009 +0000
     1.3 @@ -1173,8 +1173,9 @@
     1.4   *  
     1.5   *  \param rect   A pointer to the rectangle to read, or NULL for the entire 
     1.6   *                render target.
     1.7 - *  \param pixels A pointer to be filled in with the pixel data in the rendering
     1.8 - *                target format.
     1.9 + *  \param format The desired format of the pixel data, or 0 to use the format
    1.10 + *                of the rendering target
    1.11 + *  \param pixels A pointer to be filled in with the pixel data
    1.12   *  \param pitch  The pitch of the pixels parameter.
    1.13   *  
    1.14   *  \return 0 on success, or -1 if pixel reading is not supported.
    1.15 @@ -1182,6 +1183,7 @@
    1.16   *  \warning This is a very slow operation, and should not be used frequently.
    1.17   */
    1.18  extern DECLSPEC int SDLCALL SDL_RenderReadPixels(const SDL_Rect * rect,
    1.19 +                                                 Uint32 format,
    1.20                                                   void *pixels, int pitch);
    1.21  
    1.22  /**
    1.23 @@ -1189,6 +1191,8 @@
    1.24   *  
    1.25   *  \param rect   A pointer to the rectangle to write, or NULL for the entire 
    1.26   *                render target.
    1.27 + *  \param format The format of the pixel data, or 0 to use the format
    1.28 + *                of the rendering target
    1.29   *  \param pixels A pointer to the pixel data to write.
    1.30   *  \param pitch  The pitch of the pixels parameter.
    1.31   *  
    1.32 @@ -1197,6 +1201,7 @@
    1.33   *  \warning This is a very slow operation, and should not be used frequently.
    1.34   */
    1.35  extern DECLSPEC int SDLCALL SDL_RenderWritePixels(const SDL_Rect * rect,
    1.36 +                                                  Uint32 format,
    1.37                                                    const void *pixels,
    1.38                                                    int pitch);
    1.39  
     2.1 --- a/src/video/SDL_renderer_gl.c	Sun Nov 15 09:21:46 2009 +0000
     2.2 +++ b/src/video/SDL_renderer_gl.c	Mon Nov 16 07:13:07 2009 +0000
     2.3 @@ -103,9 +103,9 @@
     2.4  static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
     2.5                           const SDL_Rect * srcrect, const SDL_Rect * dstrect);
     2.6  static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
     2.7 -                               void * pixels, int pitch);
     2.8 +                               Uint32 pixel_format, void * pixels, int pitch);
     2.9  static int GL_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    2.10 -                                const void * pixels, int pitch);
    2.11 +                                Uint32 pixel_format, const void * pixels, int pitch);
    2.12  static void GL_RenderPresent(SDL_Renderer * renderer);
    2.13  static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    2.14  static void GL_DestroyRenderer(SDL_Renderer * renderer);
    2.15 @@ -1254,16 +1254,16 @@
    2.16  
    2.17  static int
    2.18  GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    2.19 -                    void * pixels, int pitch)
    2.20 +                    Uint32 pixel_format, void * pixels, int pitch)
    2.21  {
    2.22      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
    2.23 -    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
    2.24 -    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
    2.25 -    Uint32 pixel_format = display->current_mode.format;
    2.26      GLint internalFormat;
    2.27      GLenum format, type;
    2.28 +    Uint8 *src, *dst, *tmp;
    2.29 +    int length, rows;
    2.30  
    2.31      if (!convert_format(data, pixel_format, &internalFormat, &format, &type)) {
    2.32 +        /* FIXME: Do a temp copy to a format that is supported */
    2.33          SDL_SetError("Unsupported pixel format");
    2.34          return -1;
    2.35      }
    2.36 @@ -1275,16 +1275,52 @@
    2.37      }
    2.38      data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
    2.39      data->glPixelStorei(GL_PACK_ROW_LENGTH,
    2.40 -                        -2 * (pitch / bytes_per_pixel(pixel_format)));
    2.41 +                        (pitch / bytes_per_pixel(pixel_format)));
    2.42  
    2.43      data->glReadPixels(rect->x, rect->y+rect->h-1, rect->w, rect->h,
    2.44 -                       format, type, pixels + (rect->h-1)*pitch);
    2.45 +                       format, type, pixels);
    2.46 +
    2.47 +    /* Flip the rows to be top-down */
    2.48 +    length = rect->w * bytes_per_pixel(pixel_format);
    2.49 +    src = (Uint8*)pixels + (rect->h-1)*pitch;
    2.50 +    dst = (Uint8*)pixels;
    2.51 +    tmp = SDL_stack_alloc(Uint8, length);
    2.52 +    rows = rect->h / 2;
    2.53 +    while (rows--) {
    2.54 +        SDL_memcpy(tmp, dst, length);
    2.55 +        SDL_memcpy(dst, src, length);
    2.56 +        SDL_memcpy(src, tmp, length);
    2.57 +    }
    2.58 +    SDL_stack_free(tmp);
    2.59  }
    2.60  
    2.61  static int
    2.62  GL_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    2.63 -                     const void * pixels, int pitch)
    2.64 +                     Uint32 pixel_format, const void * pixels, int pitch)
    2.65  {
    2.66 +    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
    2.67 +    GLint internalFormat;
    2.68 +    GLenum format, type;
    2.69 +
    2.70 +    if (!convert_format(data, pixel_format, &internalFormat, &format, &type)) {
    2.71 +        /* FIXME: Do a temp copy to a format that is supported */
    2.72 +        SDL_SetError("Unsupported pixel format");
    2.73 +        return -1;
    2.74 +    }
    2.75 +
    2.76 +    /* FIXME: We need to copy the data and flip it */
    2.77 +
    2.78 +    if (pixel_format == SDL_PIXELFORMAT_INDEX1LSB) {
    2.79 +        data->glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
    2.80 +    } else if (pixel_format == SDL_PIXELFORMAT_INDEX1MSB) {
    2.81 +        data->glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
    2.82 +    }
    2.83 +    data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    2.84 +    data->glPixelStorei(GL_UNPACK_ROW_LENGTH,
    2.85 +                        (pitch / bytes_per_pixel(pixel_format)));
    2.86 +
    2.87 +    data->glReadPixels(rect->x, rect->y+rect->h-1, rect->w, rect->h,
    2.88 +                       format, type, pixels);
    2.89  }
    2.90  
    2.91  static void
     3.1 --- a/src/video/SDL_renderer_sw.c	Sun Nov 15 09:21:46 2009 +0000
     3.2 +++ b/src/video/SDL_renderer_sw.c	Mon Nov 16 07:13:07 2009 +0000
     3.3 @@ -66,9 +66,9 @@
     3.4  static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
     3.5                           const SDL_Rect * srcrect, const SDL_Rect * dstrect);
     3.6  static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
     3.7 -                               void * pixels, int pitch);
     3.8 +                               Uint32 format, void * pixels, int pitch);
     3.9  static int SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    3.10 -                                const void * pixels, int pitch);
    3.11 +                                Uint32 format, const void * pixels, int pitch);
    3.12  static void SW_RenderPresent(SDL_Renderer * renderer);
    3.13  static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    3.14  static void SW_DestroyRenderer(SDL_Renderer * renderer);
    3.15 @@ -736,12 +736,9 @@
    3.16  
    3.17  static int
    3.18  SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    3.19 -                    void * pixels, int pitch)
    3.20 +                    Uint32 format, void * pixels, int pitch)
    3.21  {
    3.22      SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
    3.23 -    const Uint8 *src;
    3.24 -    Uint8 *dst;
    3.25 -    int src_pitch, dst_pitch, w, h;
    3.26  
    3.27      if (data->renderer->LockTexture(data->renderer,
    3.28                                      data->texture[data->current_texture],
    3.29 @@ -750,17 +747,9 @@
    3.30          return -1;
    3.31      }
    3.32  
    3.33 -    src = data->surface.pixels;
    3.34 -    src_pitch = data->surface.pitch;
    3.35 -    dst = pixels;
    3.36 -    dst_pitch = pitch;
    3.37 -    h = rect->h;
    3.38 -    w = rect->w * data->surface.format->BytesPerPixel;
    3.39 -    while (h--) {
    3.40 -        SDL_memcpy(dst, src, w);
    3.41 -        src += src_pitch;
    3.42 -        dst += dst_pitch;
    3.43 -    }
    3.44 +    SDL_ConvertPixels(rect->w, rect->h,
    3.45 +                      data->format, data->surface.pixels, data->surface.pitch,
    3.46 +                      format, pixels, pitch);
    3.47  
    3.48      data->renderer->UnlockTexture(data->renderer,
    3.49                                    data->texture[data->current_texture]);
    3.50 @@ -769,12 +758,9 @@
    3.51  
    3.52  static int
    3.53  SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
    3.54 -                     const void * pixels, int pitch)
    3.55 +                     Uint32 format, const void * pixels, int pitch)
    3.56  {
    3.57      SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
    3.58 -    const Uint8 *src;
    3.59 -    Uint8 *dst;
    3.60 -    int src_pitch, dst_pitch, w, h;
    3.61  
    3.62      if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
    3.63          SDL_AddDirtyRect(&data->dirty, rect);
    3.64 @@ -787,17 +773,8 @@
    3.65          return -1;
    3.66      }
    3.67  
    3.68 -    src = pixels;
    3.69 -    src_pitch = pitch;
    3.70 -    dst = data->surface.pixels;
    3.71 -    dst_pitch = data->surface.pitch;
    3.72 -    h = rect->h;
    3.73 -    w = rect->w * data->surface.format->BytesPerPixel;
    3.74 -    while (h--) {
    3.75 -        SDL_memcpy(dst, src, w);
    3.76 -        src += src_pitch;
    3.77 -        dst += dst_pitch;
    3.78 -    }
    3.79 +    SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch,
    3.80 +                      data->format, data->surface.pixels, data->surface.pitch);
    3.81  
    3.82      data->renderer->UnlockTexture(data->renderer,
    3.83                                    data->texture[data->current_texture]);
     4.1 --- a/src/video/SDL_sysvideo.h	Sun Nov 15 09:21:46 2009 +0000
     4.2 +++ b/src/video/SDL_sysvideo.h	Mon Nov 16 07:13:07 2009 +0000
     4.3 @@ -97,9 +97,9 @@
     4.4      int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
     4.5                         const SDL_Rect * srcrect, const SDL_Rect * dstrect);
     4.6      int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
     4.7 -                             void * pixels, int pitch);
     4.8 +                             Uint32 format, void * pixels, int pitch);
     4.9      int (*RenderWritePixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
    4.10 -                              const void * pixels, int pitch);
    4.11 +                              Uint32 format, const void * pixels, int pitch);
    4.12      void (*RenderPresent) (SDL_Renderer * renderer);
    4.13      void (*DestroyTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
    4.14  
     5.1 --- a/src/video/SDL_video.c	Sun Nov 15 09:21:46 2009 +0000
     5.2 +++ b/src/video/SDL_video.c	Mon Nov 16 07:13:07 2009 +0000
     5.3 @@ -2487,7 +2487,8 @@
     5.4  }
     5.5  
     5.6  int
     5.7 -SDL_RenderReadPixels(const SDL_Rect * rect, void * pixels, int pitch)
     5.8 +SDL_RenderReadPixels(const SDL_Rect * rect, Uint32 format,
     5.9 +                     void * pixels, int pitch)
    5.10  {
    5.11      SDL_Renderer *renderer;
    5.12      SDL_Window *window;
    5.13 @@ -2503,6 +2504,10 @@
    5.14      }
    5.15      window = SDL_GetWindowFromID(renderer->window);
    5.16  
    5.17 +    if (!format) {
    5.18 +        format = SDL_GetDisplayFromWindow(window)->current_mode.format;
    5.19 +    }
    5.20 +
    5.21      real_rect.x = 0;
    5.22      real_rect.y = 0;
    5.23      real_rect.w = window->w;
    5.24 @@ -2521,11 +2526,13 @@
    5.25          }
    5.26      }
    5.27  
    5.28 -    return renderer->RenderReadPixels(renderer, &real_rect, pixels, pitch);
    5.29 +    return renderer->RenderReadPixels(renderer, &real_rect,
    5.30 +                                      format, pixels, pitch);
    5.31  }
    5.32  
    5.33  int
    5.34 -SDL_RenderWritePixels(const SDL_Rect * rect, const void * pixels, int pitch)
    5.35 +SDL_RenderWritePixels(const SDL_Rect * rect, Uint32 format,
    5.36 +                      const void * pixels, int pitch)
    5.37  {
    5.38      SDL_Renderer *renderer;
    5.39      SDL_Window *window;
    5.40 @@ -2541,6 +2548,10 @@
    5.41      }
    5.42      window = SDL_GetWindowFromID(renderer->window);
    5.43  
    5.44 +    if (!format) {
    5.45 +        format = SDL_GetDisplayFromWindow(window)->current_mode.format;
    5.46 +    }
    5.47 +
    5.48      real_rect.x = 0;
    5.49      real_rect.y = 0;
    5.50      real_rect.w = window->w;
    5.51 @@ -2559,7 +2570,8 @@
    5.52          }
    5.53      }
    5.54  
    5.55 -    return renderer->RenderWritePixels(renderer, &real_rect, pixels, pitch);
    5.56 +    return renderer->RenderWritePixels(renderer, &real_rect,
    5.57 +                                       format, pixels, pitch);
    5.58  }
    5.59  
    5.60  void
     6.1 --- a/test/automated/common/common.h	Sun Nov 15 09:21:46 2009 +0000
     6.2 +++ b/test/automated/common/common.h	Mon Nov 16 07:13:07 2009 +0000
     6.3 @@ -12,11 +12,13 @@
     6.4  
     6.5  
     6.6  #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
     6.7 +#  define FORMAT  SDL_PIXELFORMAT_RGBA8888
     6.8  #  define RMASK   0xff000000 /**< Red bit mask. */
     6.9  #  define GMASK   0x00ff0000 /**< Green bit mask. */
    6.10  #  define BMASK   0x0000ff00 /**< Blue bit mask. */
    6.11  #  define AMASK   0x000000ff /**< Alpha bit mask. */
    6.12  #else
    6.13 +#  define FORMAT  SDL_PIXELFORMAT_ABGR8888
    6.14  #  define RMASK   0x000000ff /**< Red bit mask. */
    6.15  #  define GMASK   0x0000ff00 /**< Green bit mask. */
    6.16  #  define BMASK   0x00ff0000 /**< Blue bit mask. */
     7.1 --- a/test/automated/render/render.c	Sun Nov 15 09:21:46 2009 +0000
     7.2 +++ b/test/automated/render/render.c	Mon Nov 16 07:13:07 2009 +0000
     7.3 @@ -67,7 +67,7 @@
     7.4        return 1;
     7.5  
     7.6     /* Read pixels. */
     7.7 -   ret = SDL_RenderReadPixels( NULL, pix, 80*4 );
     7.8 +   ret = SDL_RenderReadPixels( NULL, FORMAT, pix, 80*4 );
     7.9     if (SDL_ATassert( "SDL_RenderReadPixels", ret==0) )
    7.10        return 1;
    7.11