Work in progress on implementation of SDL_RenderReadPixels() and SDL_RenderWritePixels(), code untested.
authorSam Lantinga <slouken@libsdl.org>
Mon, 09 Nov 2009 05:20:11 +0000
changeset 3427 36cf454ba065
parent 3426 ee0178f1c507
child 3428 78475292e059
Work in progress on implementation of SDL_RenderReadPixels() and SDL_RenderWritePixels(), code untested.
src/video/SDL_renderer_sw.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/win32/SDL_d3drender.c
--- a/src/video/SDL_renderer_sw.c	Mon Nov 09 04:13:51 2009 +0000
+++ b/src/video/SDL_renderer_sw.c	Mon Nov 09 05:20:11 2009 +0000
@@ -65,6 +65,10 @@
 static int SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
 static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
+static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+                               void * pixels, int pitch);
+static int SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+                                const void * pixels, int pitch);
 static void SW_RenderPresent(SDL_Renderer * renderer);
 static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static void SW_DestroyRenderer(SDL_Renderer * renderer);
@@ -228,6 +232,8 @@
     renderer->RenderLine = SW_RenderLine;
     renderer->RenderFill = SW_RenderFill;
     renderer->RenderCopy = SW_RenderCopy;
+    renderer->RenderReadPixels = SW_RenderReadPixels;
+    renderer->RenderWritePixels = SW_RenderWritePixels;
     renderer->RenderPresent = SW_RenderPresent;
     renderer->DestroyRenderer = SW_DestroyRenderer;
     renderer->info.name = SW_RenderDriver.info.name;
@@ -728,6 +734,76 @@
     return status;
 }
 
+static int
+SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+                    void * pixels, int pitch)
+{
+    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
+    const Uint8 *src;
+    Uint8 *dst;
+    int src_pitch, dst_pitch, w, h;
+
+    if (data->renderer->LockTexture(data->renderer,
+                                    data->texture[data->current_texture],
+                                    rect, 0, &data->surface.pixels,
+                                    &data->surface.pitch) < 0) {
+        return -1;
+    }
+
+    src = data->surface.pixels;
+    src_pitch = data->surface.pitch;
+    dst = pixels;
+    dst_pitch = pitch;
+    h = rect->h;
+    w = rect->w * data->surface.format->BytesPerPixel;
+    while (h--) {
+        SDL_memcpy(dst, src, w);
+        src += src_pitch;
+        dst += dst_pitch;
+    }
+
+    data->renderer->UnlockTexture(data->renderer,
+                                  data->texture[data->current_texture]);
+    return 0;
+}
+
+static int
+SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+                     const void * pixels, int pitch)
+{
+    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
+    const Uint8 *src;
+    Uint8 *dst;
+    int src_pitch, dst_pitch, w, h;
+
+    if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
+        SDL_AddDirtyRect(&data->dirty, rect);
+    }
+
+    if (data->renderer->LockTexture(data->renderer,
+                                    data->texture[data->current_texture],
+                                    rect, 1, &data->surface.pixels,
+                                    &data->surface.pitch) < 0) {
+        return -1;
+    }
+
+    src = pixels;
+    src_pitch = pitch;
+    dst = data->surface.pixels;
+    dst_pitch = data->surface.pitch;
+    h = rect->h;
+    w = rect->w * data->surface.format->BytesPerPixel;
+    while (h--) {
+        SDL_memcpy(dst, src, w);
+        src += src_pitch;
+        dst += dst_pitch;
+    }
+
+    data->renderer->UnlockTexture(data->renderer,
+                                  data->texture[data->current_texture]);
+    return 0;
+}
+
 static void
 SW_RenderPresent(SDL_Renderer * renderer)
 {
--- a/src/video/SDL_sysvideo.h	Mon Nov 09 04:13:51 2009 +0000
+++ b/src/video/SDL_sysvideo.h	Mon Nov 09 05:20:11 2009 +0000
@@ -96,6 +96,10 @@
     int (*RenderFill) (SDL_Renderer * renderer, const SDL_Rect * rect);
     int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
                        const SDL_Rect * srcrect, const SDL_Rect * dstrect);
+    int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
+                             void * pixels, int pitch);
+    int (*RenderWritePixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
+                              const void * pixels, int pitch);
     void (*RenderPresent) (SDL_Renderer * renderer);
     void (*DestroyTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
 
--- a/src/video/SDL_video.c	Mon Nov 09 04:13:51 2009 +0000
+++ b/src/video/SDL_video.c	Mon Nov 09 05:20:11 2009 +0000
@@ -2486,6 +2486,82 @@
                                 &real_dstrect);
 }
 
+int
+SDL_RenderReadPixels(const SDL_Rect * rect, void * pixels, int pitch)
+{
+    SDL_Renderer *renderer;
+    SDL_Window *window;
+    SDL_Rect real_rect;
+
+    renderer = SDL_GetCurrentRenderer();
+    if (!renderer) {
+        return -1;
+    }
+    if (!renderer->RenderReadPixels) {
+        SDL_Unsupported();
+        return -1;
+    }
+    window = SDL_GetWindowFromID(renderer->window);
+
+    real_rect.x = 0;
+    real_rect.y = 0;
+    real_rect.w = window->w;
+    real_rect.h = window->h;
+    if (rect) {
+        if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
+            return 0;
+        }
+        if (real_rect.y > rect->y) {
+            pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y);
+        }
+        if (real_rect.x > rect->x) {
+            Uint32 format = SDL_CurrentDisplay.current_mode.format;
+            int bpp = SDL_BYTESPERPIXEL(format);
+            pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x);
+        }
+    }
+
+    return renderer->RenderReadPixels(renderer, &real_rect, pixels, pitch);
+}
+
+int
+SDL_RenderWritePixels(const SDL_Rect * rect, const void * pixels, int pitch)
+{
+    SDL_Renderer *renderer;
+    SDL_Window *window;
+    SDL_Rect real_rect;
+
+    renderer = SDL_GetCurrentRenderer();
+    if (!renderer) {
+        return -1;
+    }
+    if (!renderer->RenderWritePixels) {
+        SDL_Unsupported();
+        return -1;
+    }
+    window = SDL_GetWindowFromID(renderer->window);
+
+    real_rect.x = 0;
+    real_rect.y = 0;
+    real_rect.w = window->w;
+    real_rect.h = window->h;
+    if (rect) {
+        if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
+            return 0;
+        }
+        if (real_rect.y > rect->y) {
+            pixels = (const Uint8 *)pixels + pitch * (real_rect.y - rect->y);
+        }
+        if (real_rect.x > rect->x) {
+            Uint32 format = SDL_CurrentDisplay.current_mode.format;
+            int bpp = SDL_BYTESPERPIXEL(format);
+            pixels = (const Uint8 *)pixels + bpp * (real_rect.x - rect->x);
+        }
+    }
+
+    return renderer->RenderWritePixels(renderer, &real_rect, pixels, pitch);
+}
+
 void
 SDL_RenderPresent(void)
 {
--- a/src/video/win32/SDL_d3drender.c	Mon Nov 09 04:13:51 2009 +0000
+++ b/src/video/win32/SDL_d3drender.c	Mon Nov 09 05:20:11 2009 +0000
@@ -72,6 +72,8 @@
 static int D3D_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                           const SDL_Rect * srcrect, const SDL_Rect * dstrect);
+static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+                                void * pixels, int pitch);
 static void D3D_RenderPresent(SDL_Renderer * renderer);
 static void D3D_DestroyTexture(SDL_Renderer * renderer,
                                SDL_Texture * texture);
@@ -367,6 +369,7 @@
     renderer->RenderLine = D3D_RenderLine;
     renderer->RenderFill = D3D_RenderFill;
     renderer->RenderCopy = D3D_RenderCopy;
+    renderer->RenderReadPixels = D3D_RenderReadPixels;
     renderer->RenderPresent = D3D_RenderPresent;
     renderer->DestroyTexture = D3D_DestroyTexture;
     renderer->DestroyRenderer = D3D_DestroyRenderer;
@@ -1145,6 +1148,50 @@
     return 0;
 }
 
+static int
+D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+                     void * pixels, int pitch)
+{
+    BYTE * pBytes;
+    D3DLOCKED_RECT lockedRect;
+    BYTE b, g, r, a;
+    unsigned long index;
+    int cur_mouse;
+    int x, y;
+
+    LPDIRECT3DSURFACE9 backBuffer;
+    LPDIRECT3DSURFACE9 pickOffscreenSurface;
+    D3DSURFACE_DESC desc;
+
+    D3D_RenderData * data = (D3D_RenderData *) renderer->driverdata;
+    
+    IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
+    
+    
+    IDirect3DSurface9_GetDesc(backBuffer, &desc);
+
+    IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pickOffscreenSurface, NULL);
+
+    IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, pickOffscreenSurface);
+
+    IDirect3DSurface9_LockRect(pickOffscreenSurface, &lockedRect, NULL, D3DLOCK_READONLY);
+    pBytes = (BYTE*)lockedRect.pBits;
+    IDirect3DSurface9_UnlockRect(pickOffscreenSurface);
+
+    // just to debug -->
+    cur_mouse = SDL_SelectMouse(-1);
+    SDL_GetMouseState(cur_mouse, &x, &y);
+    index = (x * 4 + (y * lockedRect.Pitch));
+
+    b = pBytes[index];
+    g = pBytes[index+1];
+    r = pBytes[index+2];
+    a = pBytes[index+3];
+    // <--
+    
+    return -1;
+}
+
 static void
 D3D_RenderPresent(SDL_Renderer * renderer)
 {